Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extGraph_predes / src / com / iver / cit / gvsig / graph / core / Network.java @ 8639

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
                        flag.setDirec(GvFlag.BOTH_DIRECTIONS);
568

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

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

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

    
598
        }
599

    
600

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

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

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

    
625

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

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

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

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

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

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

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

    
670
                oldEdge = graph.getEdgeByID(idEdge);
671

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

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

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

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

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

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

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

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

    
727
        }
728

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

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

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

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

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

    
870
}