Statistics
| Revision:

svn-gvsig-desktop / tags / PilotoRedes_Build_4 / extensions / extGraph_predes / src / com / iver / cit / gvsig / graph / core / Network.java @ 12191

History | View | Annotate | Download (25.8 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.Iterator;
47
import java.util.Map;
48
import java.util.TreeMap;
49

    
50
import com.iver.cit.gvsig.fmap.DriverException;
51
import com.iver.cit.gvsig.fmap.core.IGeometry;
52
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
53
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
54
import com.iver.cit.gvsig.fmap.layers.CancelationException;
55
import com.iver.cit.gvsig.fmap.layers.FBitSet;
56
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
57
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter;
58
import com.iver.cit.gvsig.graph.GraphException;
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
        public void reconstruyeTramo(int idArc) {
79
                GvNode pN1;
80
                int i;
81
                
82
                // Si encontramos un enlace con idEdge >= numOriginalEdges, lo cambiamos.
83
                // Y CON ESE IDarc!!
84
                // Si hay varios, no pasa nada, volvemos a llamar a esta funci?n con IdTramo
85

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

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

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

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

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

    
142
        }
143

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

    
186
        }
187

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

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

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

    
209
                        case PathIterator.SEG_LINETO:
210

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

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

    
232
                                from = first;
233
                                break;
234

    
235
                        } // end switch
236

    
237
                        theIterator.next();
238
                }
239

    
240
                return resul;
241
        }
242

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

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

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

    
289
                }
290

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

    
296
                // Creamos el nodo de enmedio
297

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

    
309
                newNode = new GvNode();
310
                // Nodo = &Nodos[numNodos];
311

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

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

    
332
                encontrado = false;
333

    
334
                elIdArco = -1;
335
                elIdContraArco = -1;
336

    
337
                boolean bIdTramoYaPartido = false;
338

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

    
345
                                idNodo1 = addedEdge.getIdNodeOrig();
346
                                idNodo2 = addedEdge.getIdNodeEnd();
347

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

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

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

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

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

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

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

    
394
                } // else encontrado
395

    
396
                return newNode.getIdNode();
397

    
398
        }
399

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

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

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

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

    
473
                Coordinate[] coords = jtsGeom.getCoordinates();
474

    
475
                Coordinate userCoord = new Coordinate(x, y);
476

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

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

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

    
514
                return pct;
515
        }
516

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

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

    
550
        }
551

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

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

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

    
585
        }
586

    
587
        /**
588
         * Create a flag in both directions, but NOT add it to the Network.
589
         * We use it on onetomany solver
590
         * @param x
591
         * @param y
592
         * @param tol
593
         * @return
594
         * @throws GraphException
595
         */
596
        public GvFlag createFlag(double x, double y, double tol) throws GraphException {
597
                try {
598
                        Point2D nearestPoint = new Point2D.Double();
599
                        int idArc = findClosestArc(x, y, tol, nearestPoint);
600
                        if (idArc == -1)
601
                                return null;
602

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

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

    
616
        }
617

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

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

    
636
        }
637

    
638

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

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

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

    
663

    
664
        public void setFlags(ArrayList flags) {
665
                this.flags = flags;
666
        }
667

    
668
        public IGraph getGraph() {
669
                return graph;
670
        }
671

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

    
678
        public FLyrVect getLayer() {
679
                return lyrVect;
680
        }
681

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

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

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

    
708
                oldEdge = graph.getEdgeByID(idEdge);
709

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

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

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

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

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

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

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

    
763
                newNode.getEnlaces().add(second);
764

    
765
        }
766

    
767
        public ArrayList getModifiedCosts() {
768
                return modifiedCosts;
769
                
770
        }
771

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

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

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

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

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

    
931
}