Statistics
| Revision:

root / trunk / extensions / extGraph_predes / src / com / iver / cit / gvsig / graph / core / Network.java @ 8700

History | View | Annotate | Download (24.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

    
47
import com.iver.cit.gvsig.fmap.DriverException;
48
import com.iver.cit.gvsig.fmap.EventBuffer;
49
import com.iver.cit.gvsig.fmap.core.IGeometry;
50
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
51
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
52
import com.iver.cit.gvsig.fmap.layers.CancelationException;
53
import com.iver.cit.gvsig.fmap.layers.FBitSet;
54
import com.iver.cit.gvsig.fmap.layers.FLayer;
55
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
56
import com.iver.cit.gvsig.fmap.layers.LayerListenerAdapter;
57
import com.iver.cit.gvsig.fmap.layers.LayerPositionEvent;
58
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter;
59
import com.iver.cit.gvsig.graph.GraphException;
60
import com.iver.utiles.swing.threads.Cancellable;
61
import com.vividsolutions.jts.geom.Coordinate;
62
import com.vividsolutions.jts.geom.LineSegment;
63
import com.vividsolutions.jts.geom.MultiLineString;
64

    
65
public class Network {
66
        protected FLyrVect lyrVect;
67

    
68
        protected IGraph graph;
69

    
70
        protected ArrayList flags = new ArrayList();
71

    
72
        protected int numOriginalEdges;
73

    
74
        protected int numOriginalNodes;
75

    
76
        private ArrayList modifiedCosts = new ArrayList();
77
        private ArrayList flagListeners = new ArrayList();
78
        private boolean dispatching = true;
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
         * @return
152
         */
153
        public int findClosestArc(double x, double y, double tolerance) {
154
                Point2D p = new Point2D.Double(x, y);
155
                FBitSet bitSet;
156
                try {
157
                        bitSet = lyrVect.queryByPoint(p, tolerance);
158
                        VectorialAdapter va = (VectorialAdapter) lyrVect.getSource();
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
                                        }
172
                                }
173
                        }
174
                        return foundGeom;
175
                } catch (DriverException e1) {
176
                        // TODO Auto-generated catch block
177
                        e1.printStackTrace();
178
                } catch (DriverIOException e) {
179
                        // TODO Auto-generated catch block
180
                        e.printStackTrace();
181
                }
182
                return -1;
183

    
184
        }
185

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

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

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

    
207
                        case PathIterator.SEG_LINETO:
208

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

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

    
230
                                from = first;
231
                                break;
232

    
233
                        } // end switch
234

    
235
                        theIterator.next();
236
                }
237

    
238
                return resul;
239
        }
240

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

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

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

    
287
                }
288

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

    
294
                // Creamos el nodo de enmedio
295

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

    
307
                newNode = new GvNode();
308
                // Nodo = &Nodos[numNodos];
309

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

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

    
330
                encontrado = false;
331

    
332
                elIdArco = -1;
333
                elIdContraArco = -1;
334

    
335
                boolean bIdTramoYaPartido = false;
336

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

    
343
                                idNodo1 = addedEdge.getIdNodeOrig();
344
                                idNodo2 = addedEdge.getIdNodeEnd();
345

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

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

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

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

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

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

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

    
392
                } // else encontrado
393

    
394
                return newNode.getIdNode();
395

    
396
        }
397

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

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

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

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

    
470
                Coordinate[] coords = jtsGeom.getCoordinates();
471

    
472
                Coordinate userCoord = new Coordinate(x, y);
473

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

    
491
                        Coordinate auxPoint = line.closestPoint(userCoord);
492
                        dist = userCoord.distance(auxPoint);
493
                        if ((dist < minDist)) {
494
                                minDist = dist;
495
                                cOrig = c1;
496
                                closestPoint = auxPoint;
497
                                distTo = longReal;
498
                        }
499
                        longReal += line.getLength();
500
                }
501

    
502
                dist = cOrig.distance(closestPoint);
503
                double longBuscada = distTo + dist;
504

    
505
                double pct;
506
                if (longReal > 0)
507
                        pct = longBuscada / longReal;
508
                else
509
                        pct = 0.0;
510

    
511
                return pct;
512
        }
513

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

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

    
546
        }
547

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

    
565
                        GvFlag flag = new GvFlag(x, y);
566
                        flag.setIdArc(idArc);
567
                        EdgePair edgePair = graph.getEdgesByIdArc(idArc);
568
                        flag.setDirec(GvFlag.BOTH_DIRECTIONS);
569

    
570
                        flag.setPct(percentAlong(idArc, x, y));
571
                        flag.setIdFlag(flags.size());
572
                        flags.add(flag);
573
                        callFlagsChanged(IFlagListener.FLAG_ADDED);
574
                        return flag;
575
                } catch (DriverIOException e) {
576
                        e.printStackTrace();
577
                        throw new GraphException(e);
578
                }
579

    
580
        }
581
        
582
        public GvFlag addFlagToNode(double x, double y, double tol) throws GraphException {
583
                int idArc = findClosestArc(x, y, tol);
584
                if (idArc == -1)
585
                        return null;
586

    
587
                GvFlag flag = new GvFlag(x, y);
588
                flag.setIdArc(idArc);
589
                flag.setDirec(GvFlag.BOTH_DIRECTIONS);
590
                int idNode = getClosestIdNode(flag);
591
                
592
                GvNode node = graph.getNodeByID(idNode);
593
                flag.setOriginalPoint(node.getX(), node.getY());
594
                flag.setIdFlag(flags.size());
595
                flags.add(flag);
596
                callFlagsChanged(IFlagListener.FLAG_ADDED);
597
                return flag;
598

    
599
        }
600

    
601

    
602
        public void addFlag(GvFlag flag) {
603
                flags.add(flag);
604
                callFlagsChanged(IFlagListener.FLAG_ADDED);
605
        }
606

    
607
        public GvFlag[] getFlags() {
608
                ArrayList aux = new ArrayList();
609
                for (int i=0; i < getOriginaFlags().size(); i++)
610
                {
611
                        GvFlag flag = (GvFlag) getOriginaFlags().get(i);
612
                        if (flag.isEnabled()) aux.add(flag);
613
                }
614

    
615
                return (GvFlag[]) aux.toArray(new GvFlag[0]);
616
        }
617
        
618
        /**
619
         * Suitable to change directly the flags collection
620
         * @return
621
         */
622
        public ArrayList getOriginaFlags() {
623
                return flags;
624
        }
625

    
626

    
627
        public void setFlags(ArrayList flags) {
628
                this.flags = flags;
629
        }
630

    
631
        public IGraph getGraph() {
632
                return graph;
633
        }
634

    
635
        public void setGraph(IGraph graph) {
636
                this.graph = graph;
637
                numOriginalEdges = graph.numEdges();
638
                numOriginalNodes = graph.numVertices();
639
        }
640

    
641
        public FLyrVect getLayer() {
642
                return lyrVect;
643
        }
644

    
645
        public void setLayer(FLyrVect lyr) {
646
                this.lyrVect = lyr;
647
        }
648

    
649
        public void removeFlags() {
650
                flags = new ArrayList();
651
                callFlagsChanged(IFlagListener.FLAG_REMOVED);
652
        }
653
        
654
        public void removeFlag(GvFlag flag){
655
                flags.remove(flag);
656
                callFlagsChanged(IFlagListener.FLAG_REMOVED);
657
        }
658

    
659
        void PartirArco(int idEdge, int idNode) {
660
                // Se supone que el nuevo Nodo YA est? creado. Aqui dentro se coge el
661
                // arco viejo y se le pega un tajo.
662
                // (Se modifican los enlaces de los nodos de ese arco y se crean los
663
                // arcos nuevos, fijando sus costes).
664
                // Para sacar el porcentaje nos aprovechamos de que el nuevo nodo est?
665
                // puesto en base a ese porcentaje
666
                // en distancia de los extremos.
667
                GvEdge oldEdge;
668
                GvNode pN1, pN2;
669
                double pct;
670

    
671
                oldEdge = graph.getEdgeByID(idEdge);
672

    
673
                // OJO, controlando los ceros por si acaso la recta es horizontal o
674
                // vertical (Y si mide cero???)
675

    
676
                // pN1 = &Nodos[Arcos[idArco].idNodo1];
677
                // pN2 = &Nodos[Arcos[idArco].idNodo2];
678
                pN1 = graph.getNodeByID(graph.getEdgeByID(idEdge).getIdNodeOrig());
679
                pN2 = graph.getNodeByID(graph.getEdgeByID(idEdge).getIdNodeEnd());
680
                GvNode newNode = graph.getNodeByID(idNode);
681

    
682
                if (newNode.getX() != pN1.getX())
683
                        pct = Math.abs((newNode.getX() - pN1.getX())
684
                                        / (pN2.getX() - pN1.getX()));
685
                else
686
                        pct = Math.abs((newNode.getY() - pN1.getY())
687
                                        / (pN2.getY() - pN1.getY()));
688

    
689
                GvEdge first = new GvEdge();
690
                first.setIdEdge(graph.numEdges());
691
                first.setIdArc(oldEdge.getIdArc());
692
                first.setDistance(oldEdge.getDistance() * pct);
693
                first.setWeight(oldEdge.getWeight() * pct);
694

    
695
                first.setDirec(oldEdge.getDirec());
696
                first.setIdNodeOrig(oldEdge.getIdNodeOrig());
697
                first.setType(oldEdge.getType());
698
                first.setIdNodeEnd(idNode);
699
                graph.addEdge(first);
700

    
701
                GvEdge second = new GvEdge();
702
                second.setIdEdge(graph.numEdges());
703
                second.setDistance(oldEdge.getDistance() * (1.0 - pct));
704
                second.setWeight(oldEdge.getWeight() * (1.0 - pct));
705
                second.setIdArc(oldEdge.getIdArc());
706
                second.setDirec(oldEdge.getDirec());
707
                second.setType(oldEdge.getType());
708
                second.setIdNodeOrig(idNode);
709
                second.setIdNodeEnd(oldEdge.getIdNodeEnd());
710
                graph.addEdge(second);
711

    
712
                // ////////////////////////////////////////////////////
713
                // Ahora retocamos los enlaces que salen de cada nodo
714
                // ////////////////////////////////////////////////////
715
                int i;
716
                // boolean encontrado = false;
717
                for (i = 0; i < pN1.getEnlaces().size(); i++) {
718
                        GvEdge aux = (GvEdge) pN1.getEnlaces().get(i);
719
                        if (aux.getIdEdge() == idEdge) {
720
                                pN1.getEnlaces().set(i, first);
721
                                // encontrado = true;
722
                                break;
723
                        }
724
                } // for
725

    
726
                newNode.getEnlaces().add(second);
727

    
728
        }
729

    
730
        public ArrayList getModifiedCosts() {
731
                return modifiedCosts;
732
                
733
        }
734

    
735
        /**
736
         * Create, add and apply a new modified cost to the graph. 
737
         * @param idArc where the cost will be applied.
738
         * @param newCost. -1 if you want tu put a BARRIER.
739
         * @param direction. 1-> edge of digitalized direction. 2-> inverse edge. 3-> Both directions
740
         */
741
        public GvModifiedCost addModifiedCost(int idArc, double newCost, int direction) {
742
                GvModifiedCost modifiedCost = new GvModifiedCost(idArc, newCost, direction);
743
                EdgePair edgePair = getGraph().getEdgesByIdArc(idArc);
744
                modifiedCost.setIdEdge(edgePair.idEdge);
745
                modifiedCost.setIdInverseEdge(edgePair.idInverseEdge);
746
                if (direction == 3)
747
                {
748
                        if (edgePair.getIdEdge() != -1)
749
                        {
750
                                GvEdge edge = getGraph().getEdgeByID(edgePair.getIdEdge());
751
                                modifiedCost.setOldCost(edge.getWeight());
752
                                edge.setWeight(-1.0);
753
                        }
754
                        if (edgePair.getIdInverseEdge() != -1)
755
                        {
756
                                GvEdge inverseEdge = getGraph().getEdgeByID(edgePair.getIdInverseEdge());
757
                                modifiedCost.setOldInverseCost(inverseEdge.getWeight());
758
                                inverseEdge.setWeight(-1.0);
759
                        }
760
                }
761
                if (direction == 1)
762
                {
763
                        if (edgePair.getIdEdge() != -1)
764
                        {
765
                                GvEdge edge = getGraph().getEdgeByID(edgePair.getIdEdge());
766
                                modifiedCost.setOldCost(edge.getWeight());
767
                                edge.setWeight(-1.0);
768
                        }
769
                }
770
                if (direction == 2)
771
                {
772
                        if (edgePair.getIdInverseEdge() != -1)
773
                        {
774
                                GvEdge inverseEdge = getGraph().getEdgeByID(edgePair.getIdInverseEdge());
775
                                modifiedCost.setOldInverseCost(inverseEdge.getWeight());
776
                                inverseEdge.setWeight(-1.0);
777
                        }
778
                }
779
                modifiedCosts.add(modifiedCost);
780
                modifiedCost.setApplied(true);
781
                return modifiedCost;
782
        }
783

    
784
        /**
785
         * Be careful about the ORDER!!!!
786
         * @param modifiedCost
787
         */
788
        public boolean removeModifiedCost(GvModifiedCost modifiedCost) {
789
                if (!modifiedCosts.remove(modifiedCost))
790
                        return false;
791
                int idArc = modifiedCost.getIdArc();
792
                int direction = modifiedCost.getDirection();
793
                EdgePair edgePair = getGraph().getEdgesByIdArc(idArc);
794
                if (direction == 3)
795
                {
796
                        if (edgePair.getIdEdge() != -1)
797
                        {
798
                                GvEdge edge = getGraph().getEdgeByID(edgePair.getIdEdge());
799
                                edge.setWeight(modifiedCost.getOldCost());
800
                        }
801
                        if (edgePair.getIdInverseEdge() != -1)
802
                        {
803
                                GvEdge inverseEdge = getGraph().getEdgeByID(edgePair.getIdInverseEdge());
804
                                inverseEdge.setWeight(modifiedCost.getOldInverseCost());
805
                        }
806
                }
807
                if (direction == 1)
808
                {
809
                        if (edgePair.getIdEdge() != -1)
810
                        {
811
                                GvEdge edge = getGraph().getEdgeByID(edgePair.getIdEdge());
812
                                edge.setWeight(modifiedCost.getOldCost());
813
                        }
814
                }
815
                if (direction == 2)
816
                {
817
                        if (edgePair.getIdInverseEdge() != -1)
818
                        {
819
                                GvEdge inverseEdge = getGraph().getEdgeByID(edgePair.getIdInverseEdge());
820
                                inverseEdge.setWeight(modifiedCost.getOldInverseCost());
821
                        }
822
                }
823
                return true;
824
        }
825

    
826
        public void addFlagListener(IFlagListener listener) {
827
                if (!flagListeners.contains(listener)) {
828
                        flagListeners.add(listener);
829
                }
830
        }
831
        
832
        private void callFlagsChanged(int reason) {
833
                if (dispatching) {
834
                        for (int i=0; i < flagListeners.size(); i++)
835
                        {
836
                                IFlagListener listener = (IFlagListener) flagListeners.get(i);
837
                                listener.flagsChanged(reason);
838
                        }
839
                }
840
        }
841
        
842
        /**
843
         * Useful to do batch modifies. (For example, add lot of flags
844
         * and when finished (endModifying), throw event.
845
         */
846
        public void beginModifyingFlags() {
847
                dispatching = false;
848
        }
849

    
850
        public void endModifyingFlags() {
851
                dispatching = true;
852
                callFlagsChanged(IFlagListener.FLAG_MANY_CHANGES);
853
        }
854
        /**
855
         * Mueve un flag de la posici?n from a la posici?n to.
856
         *
857
         * @param from origen.
858
         * @param to destino.
859
         * 
860
         */
861
        public void moveTo(int from, int to) throws CancelationException {
862
                int newfrom=flags.size()-from-1;
863
                int newto=flags.size()-to-1;
864
                if ( newfrom < 0 || newfrom >=flags.size() || newto < 0 || newto >= flags.size()) return;
865
                GvFlag aux = (GvFlag) flags.get(newfrom);
866
                flags.remove(newfrom);
867
                flags.add(newto, aux);
868
                callFlagsChanged(IFlagListener.FLAG_REORDER);
869
        }
870

    
871
}