Statistics
| Revision:

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

History | View | Annotate | Download (15 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.core.IGeometry;
49
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
50
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
51
import com.iver.cit.gvsig.fmap.layers.FBitSet;
52
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
53
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter;
54
import com.vividsolutions.jts.geom.Coordinate;
55
import com.vividsolutions.jts.geom.LineSegment;
56

    
57
public class Network {
58
        protected FLyrVect lyrVect;
59
        protected IGraph graph;
60
        protected ArrayList flags = new ArrayList();
61
        
62
        public void reconstruyeTramo(int idArc) {
63
                // TODO Auto-generated method stub
64
                
65
        }
66

    
67
        
68
        private int findClosestArc(double x, double y, double tolerance)
69
        {        
70
                Point2D p = new Point2D.Double(x, y);
71
                FBitSet bitSet;
72
                try {
73
                        bitSet = lyrVect.queryByPoint(p, tolerance);
74
                        VectorialAdapter va = (VectorialAdapter) lyrVect.getSource();
75
                        int counter = 0;
76
                        double minDist = tolerance;
77
                        int foundGeom = -1;
78
                        for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet
79
                                        .nextSetBit(i + 1)) {
80
                                IGeometry geom;
81
                                geom = va.getShape(i);
82
                                Point2D nearest = getNearestPoint(p, geom, tolerance);
83
                                if (nearest != null)
84
                                {
85
                                        double dist = nearest.distance(p);
86
                                        if (dist < minDist)
87
                                        {
88
                                                minDist = dist;
89
                                                foundGeom = i;
90
                                        }
91
                                }
92
                        }
93
                        return foundGeom;
94
                } catch (DriverException e1) {
95
                        // TODO Auto-generated catch block
96
                        e1.printStackTrace();
97
                } catch (DriverIOException e) {
98
                        // TODO Auto-generated catch block
99
                        e.printStackTrace();
100
                }
101
                return -1;
102
                
103
                
104
        }
105
        
106
        protected Point2D getNearestPoint(Point2D point, IGeometry geom, double tolerance) {
107
                Point2D resul = null;
108
                Coordinate c = new Coordinate(point.getX(), point.getY());
109
                
110
                PathIterator theIterator = geom.getPathIterator(null, FConverter.FLATNESS); //polyLine.getPathIterator(null, flatness);
111
                double[] theData = new double[6];
112
                double minDist = tolerance;
113
                Coordinate from = null, first = null;
114
                while (!theIterator.isDone()) {
115
                        //while not done
116
                        int theType = theIterator.currentSegment(theData);
117

    
118
                        switch (theType) {
119
                                case PathIterator.SEG_MOVETO:
120
                                        from = new Coordinate(theData[0], theData[1]);
121
                                        first = from;
122
                                        break;
123

    
124
                                case PathIterator.SEG_LINETO:
125

    
126
                                        // System.out.println("SEG_LINETO");
127
                                        Coordinate to = new Coordinate(theData[0], theData[1]);
128
                                        LineSegment line = new LineSegment(from, to);
129
                                        Coordinate closestPoint = line.closestPoint(c);
130
                                        double dist = c.distance(closestPoint);
131
                                        if ((dist < minDist)) {
132
                                                resul = new Point2D.Double(closestPoint.x, closestPoint.y);
133
                                                minDist = dist;
134
                                        }
135
                                        
136
                                        from = to;
137
                                        break;
138
                                case PathIterator.SEG_CLOSE:
139
                                        line = new LineSegment(from, first);
140
                                        closestPoint = line.closestPoint(c);
141
                                        dist = c.distance(closestPoint);
142
                                        if ((dist < minDist)) {
143
                                                resul = new Point2D.Double(closestPoint.x, closestPoint.y);
144
                                                minDist = dist;
145
                                        }
146
                                        
147
                                        from = first;
148
                                        break;
149
                                        
150

    
151
                        } //end switch
152

    
153
                        theIterator.next();
154
                }
155

    
156
                return resul;
157
        }
158
        
159
        /**
160
         * TODO: POR TERMINAR!!!
161
         * @param flag
162
         * @return
163
         */
164
        public int creaArcosVirtualesComplejo(GvFlag flag) {
165
//                 Devuelve el idNodo del nodo virtual creado.
166
                /*        0.- Creamos el nuevo Nodo virtual.
167
                        1.- Recorremos los arcos nuevos mirando su idTramo.
168
                        2.- Si existe ese idtramo=> Ya hemos partido antes ese idTramo. Buscamos el arco virtual que contiene
169
                                ese nodo y lo partimos. Ojo, recorrer hasta el final los tramos para asegurarnos de que es el trozo
170
                                m?s peque?o.
171
                        3.- Si NO existe, utilizamos el IndiceArcos para coger los arcos que toca y partirlos.
172

173
                  4.- OJO: Si el porcentaje es 0 ? 100, no partimos el arco, devolvemos el id del nodo que toca.
174
                */
175
                        // NUEVO: 20/7/2004:
176
                        // Cuando trabajamos con sentidos, al partir un arco no podemos insertar 2 nuevos sin mirar
177
                        // si es o no de un ?nico sentido.) (Mirar idArco. Si es -1, no partimos el arco).
178
                        // FIN NUEVO
179

    
180
                        int idNodo1, idNodo2;
181
                        int idArco, elIdArco, elIdContraArco;
182
                        boolean encontrado;
183
                        GvNode newNode;
184

    
185
                                // Sacamos los idNodos del tramo
186
                        EdgePair edgePair = graph.getEdgesByIdArc(flag.getIdArc());
187
                        if (edgePair.getIdEdge() != -1)
188
                        {
189
//                                idNodo1 = Arcos[IndiceArcos[idTramo].idArco].idNodo1;
190
//                                idNodo2 = Arcos[IndiceArcos[idTramo].idArco].idNodo2;
191
                                idNodo1 = graph.getEdgeByID(edgePair.getIdEdge()).getIdNodeOrig();
192
                                idNodo2 = graph.getEdgeByID(edgePair.getIdEdge()).getIdNodeEnd();
193
                                
194
                        }
195
                        else
196
                        {
197
//                                idNodo2 = Arcos[IndiceArcos[idTramo].idContraArco].idNodo1;
198
//                                idNodo1 = Arcos[IndiceArcos[idTramo].idContraArco].idNodo2;
199
                                idNodo2 = graph.getEdgeByID(edgePair.getIdInverseEdge()).getIdNodeOrig();
200
                                idNodo1 = graph.getEdgeByID(edgePair.getIdInverseEdge()).getIdNodeEnd();
201
                                
202
                        }
203

    
204
                        if (flag.getPct() == 0)
205
                                return idNodo1;
206
                        if (flag.getPct() == 1) 
207
                                return idNodo2;
208

    
209
                        // Creamos el nodo de enmedio
210

    
211
//                        if (numNodos == maxNodos) // La jodimos, T?rtola, hay que usar reallocate
212
//                        {
213
//                                // NOTA: ESTO EN DEBUG HACE QUE FALLE AL USAR DESPUES EnlacesSTL. ES POR NO S? QU? HISTORIA
214
//                                // DEL HEAP. EN RELEASE NO FALLA. (TAMPOCO S? SI FASTIDIA ALGO).
215
//                                Nodos = (CNode *) realloc(Nodos,(numNodos + MAX_RESERVA_NODOS) * sizeof(CNode)); // Deber?amos chequear que devuelve algo correcto
216
//                                maxNodos = numNodos + MAX_RESERVA_NODOS;
217
//                        }
218
                        
219
                        newNode = new GvNode();
220
                        // Nodo = &Nodos[numNodos];
221
                        
222
//                        pNuevoNodo->idNodo = numNodos;
223
                        newNode.setIdNode(graph.numVertices());
224

    
225
                        
226

    
227
                        // OJO: Las coordenadas estas puede que no tengan que ver con la realidad. Algo m?s correcto
228
                        // ser?a tener en cuenta el shape de verdad, pero creo que no influye en el resultado final.
229
//                        pNuevoNodo->x = Nodos[idNodo1].x + (Nodos[idNodo2].x - Nodos[idNodo1].x) * Porcentaje;
230
//                        pNuevoNodo->y = Nodos[idNodo1].y + (Nodos[idNodo2].y - Nodos[idNodo1].y) * Porcentaje;
231
                        GvNode node1 = graph.getNodeByID(idNodo1);
232
                        GvNode node2 = graph.getNodeByID(idNodo2);
233
                        newNode.setX(node1.getX() + (node2.getX() - node1.getX()) * flag.getPct());
234
                        newNode.setY(node1.getY() + (node2.getY() - node1.getY()) * flag.getPct());
235

    
236
                        encontrado = false;
237

    
238
                        elIdArco = -1;
239
                        elIdContraArco = -1;
240

    
241
                        boolean bIdTramoYaPartido = false;
242

    
243
                        // TODO: POR AQUI VOY
244
                        /* for (idArco = numArcosOriginal; idArco < numArcos; idArco++)
245
                        {
246
                                if (Arcos[idArco].idTramo == idTramo)
247
                                {
248
                                        bIdTramoYaPartido = true;
249

250
                                        idNodo1 = Arcos[idArco].idNodo1;
251
                                        idNodo2 = Arcos[idArco].idNodo2;
252

253
                                        // Comprobamos si est? enmedio
254
                        
255
                                        CVector2 vA(Nodos[idNodo1].x, Nodos[idNodo1].y);
256
                                        CVector2 vB(Nodos[idNodo2].x, Nodos[idNodo2].y);
257
                                        CVector2 vPoint(pNuevoNodo->x, pNuevoNodo->y);
258

259
                                        CVector2 vVector1 = vPoint - vA;
260

261
                                        // Create a normalized direction vector from end point vA to end point vB
262
                                        CVector2 vVector2 = Normalize(vB - vA);
263

264
                                        // Use the distance formula to find the distance of the line segment (or magnitude)
265
                                        double d = Distance(vA, vB);
266

267
                                        // Using the dot product, we project the vVector1 onto the vector vVector2.
268
                                        // This essentially gives us the distance from our projected vector from vA.
269
                                        double t = Dot(vVector2, vVector1);
270

271
                                        // Si la proyecci?n es positiva y menor que la magnitud d, est? en medio
272
                                    if ((t >= 0) && (t <= d)) 
273
                                        {
274
                                                encontrado = true;
275
                                                if (t==0) return idNodo1; // No partimos
276
                                                if (t==d) return idNodo2; // Tampoco partimos
277

278
                                                if (Arcos[idArco].sentido)
279
                                                        elIdArco = idArco;
280
                                                else
281
                                                        elIdContraArco = idArco;
282

283
                                        } // if est? enmedio
284
                                } // if idTramo encontrado
285
                        } // for idArco
286
                        if (bIdTramoYaPartido && (! encontrado)) 
287
                                MessageBox(NULL,"Algo va mal con lo del producto escalar","",MB_OK);
288

289

290
                        if (encontrado)
291
                        {
292
//                                sprintf(Mensaje,"Voy a partir el idTramo= %ld (idArco %ld)",idTramo,elIdArco);
293
                                // MessageBox(NULL,Mensaje,"",MB_OK);
294
                                if (elIdArco != -1)
295
                                        PartirArco(elIdArco, numNodos);
296

297
                                if (elIdContraArco != -1)
298
                                        PartirArco(elIdContraArco, numNodos);
299
                        }
300
                        else
301
                        {
302
                                // Creamos 2 Arcos por cada arco que ten?amos antes.
303
                                if (IndiceArcos[idTramo].idArco != -1)
304
                                        PartirArco(IndiceArcos[idTramo].idArco, numNodos);
305

306
                                if (IndiceArcos[idTramo].idContraArco != -1)
307
                                        PartirArco(IndiceArcos[idTramo].idContraArco, numNodos);
308

309
                        } // else encontrado
310

311
                        numNodos++;
312
                        return (numNodos -1); */
313
                        return graph.numVertices();
314
                
315
        }
316

    
317
        /**
318
         * TODO: Por ahora, cogemos el nodo m?s cercano. Lo correcto
319
         * es a?adir un nuevo nodo que divida el arco, y devolver el 
320
         * id de ese nodo.
321
         * @param flag
322
         * @return
323
         */
324
        public int creaArcosVirtuales(GvFlag flag) {
325
                EdgePair pair = graph.getEdgesByIdArc(flag.getIdArc());
326
                if (pair.getIdEdge() != -1)
327
                {
328
                        GvEdge edge = graph.getEdgeByID(pair.getIdEdge());
329
                        GvNode from = graph.getNodeByID(edge.getIdNodeOrig());
330
                        GvNode to = graph.getNodeByID(edge.getIdNodeEnd());
331
                        
332
                        double dist1 = flag.getOriginalPoint().distance(from.getX(), from.getY());
333
                        double dist2 = flag.getOriginalPoint().distance(to.getX(), to.getY());
334
                        if (dist1 < dist2)
335
                                return from.getIdNode();
336
                        else
337
                                return to.getIdNode();
338
//                        if (flag.getPct() > 0.5)
339
//                                return to.getIdNode();
340
//                        else        
341
//                                return from.getIdNode();
342
                }
343
                else
344
                {
345
                        GvEdge edge = graph.getEdgeByID(pair.getIdInverseEdge());
346
                        GvNode from = graph.getNodeByID(edge.getIdNodeOrig());
347
                        GvNode to = graph.getNodeByID(edge.getIdNodeEnd());
348

    
349
                        double dist1 = flag.getOriginalPoint().distance(from.getX(), from.getY());
350
                        double dist2 = flag.getOriginalPoint().distance(to.getX(), to.getY());
351
                        if (dist1 < dist2)
352
                                return from.getIdNode();
353
                        else
354
                                return to.getIdNode();
355

    
356
//                        if (flag.getPct() < 0.5)
357
//                                return to.getIdNode();
358
//                        else        
359
//                                return from.getIdNode();                        
360
                }
361
        }
362
        
363
        /**
364
         * @param idArc
365
         * @param x
366
         * @param y
367
         * @return entre 0.0 y 1.0
368
         */
369
        private double percentAlong(long idArc, double x, double y)
370
        {
371
                return 0;
372
        }
373
        
374
        /**
375
         * Adds a flag on a network. flagDirection set if the flag
376
         * must be on left or right edge.
377
         * @param x
378
         * @param y
379
         * @param flagDirection
380
         * @param tol tolerance in map units
381
         * @return null if there is no place to add flag.
382
         *  You can increase the tolerance, then. 
383
         */
384
        public GvFlag addFlag(double x, double y, int flagDirection, double tol)
385
        {
386
                int idArc = findClosestArc(x, y, tol);
387
                if (idArc == -1)
388
                        return null;
389
                GvFlag flag = new GvFlag(x,y);
390
                flag.setIdArc(idArc);
391
                flag.setPct(percentAlong(idArc, x, y));
392
                flag.setDirec(flagDirection);
393
                flag.setIdFlag(flags.size());
394
                return flag;                
395
        }
396

    
397
        /**
398
         * Adds 2 flags on a network. (On both sides of an arc)
399
         * @param x
400
         * @param y
401
         * @param tol tolerance in map units
402
         * @return null if there is no place to add flag.
403
         *  You can increase the tolerance, then. 
404
         */        
405
        public GvFlag addFlag(double x, double y, double tol)
406
        {
407
                int idArc = findClosestArc(x, y, tol);
408
                if (idArc == -1)
409
                        return null;
410
                
411
                GvFlag flag = new GvFlag(x, y);
412
                flag.setIdArc(idArc);
413
                flag.setDirec(GvFlag.BOTH_DIRECTIONS);
414
                flag.setPct(percentAlong(idArc, x, y));
415
                flag.setIdFlag(flags.size());
416
                flags.add(flag);
417
                return flag;
418
        }
419

    
420
        
421
        public void addFlag(GvFlag flag) {
422
                flags.add(flag);
423
        }
424
        public GvFlag[] getFlags() {
425
                return (GvFlag[]) flags.toArray(new GvFlag[0]);
426
        }
427
        public void setFlags(ArrayList flags) {
428
                this.flags = flags;
429
        }
430
        public IGraph getGraph() {
431
                return graph;
432
        }
433
        public void setGraph(IGraph graph) {
434
                this.graph = graph;
435
        }
436
        public FLyrVect getLayer() {
437
                return lyrVect;
438
        }
439
        public void setLayer(FLyrVect lyr) {
440
                this.lyrVect = lyr;
441
        }
442

    
443

    
444
        public void removeFlags() {
445
                flags = new ArrayList();                
446
        }
447
        
448
        void PartirArco(int idEdge, int idNode)
449
        {
450
                // Se supone que el nuevo Nodo YA est? creado. Aqui dentro se coge el arco viejo y se le pega un tajo.
451
                // (Se modifican los enlaces de los nodos de ese arco y se crean los arcos nuevos, fijando sus costes).
452
                // Para sacar el porcentaje nos aprovechamos de que el nuevo nodo est? puesto en base a ese porcentaje
453
                // en distancia de los extremos.
454
                GvEdge newEdge;
455
                GvEdge oldEdge;
456
                GvNode pN1, pN2;
457
                double pct;
458
                
459
                        oldEdge = graph.getEdgeByID(idEdge);
460

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

    
463
//                        pN1 = &Nodos[Arcos[idArco].idNodo1];
464
//                        pN2 = &Nodos[Arcos[idArco].idNodo2];
465
                        pN1 = graph.getNodeByID(graph.getEdgeByID(idEdge).getIdNodeOrig());
466
                        pN2 = graph.getNodeByID(graph.getEdgeByID(idEdge).getIdNodeEnd());
467
                        GvNode newNode = graph.getNodeByID(idNode);
468
                        
469
                        if (newNode.getX() != pN1.getX())
470
                                pct = Math.abs((newNode.getX() - pN1.getX())/(pN2.getX()-pN1.getX()));
471
                        else
472
                                pct = Math.abs((newNode.getY() - pN1.getY())/(pN2.getY()-pN1.getY()));
473

    
474

    
475

    
476
                        GvEdge first = new GvEdge();
477
                        first.setIdEdge(graph.numEdges());
478
                        first.setIdArc(oldEdge.getIdArc());
479
                        first.setDistance(oldEdge.getDistance() * pct);
480
                        first.setWeight(oldEdge.getWeight() * pct);
481

    
482
                        first.setDirec(oldEdge.getDirec());
483
                        first.setIdNodeOrig(oldEdge.getIdNodeOrig());
484
                        first.setType(oldEdge.getType());
485
                        first.setIdNodeEnd(idNode);
486
                        graph.addEdge(first);
487

    
488
                        GvEdge second = new GvEdge();
489
                        second.setIdEdge(graph.numEdges());
490
                        second.setDistance(oldEdge.getDistance()*(1.0-pct));
491
                        second.setWeight(oldEdge.getWeight()*(1.0-pct));
492
                        second.setIdArc(oldEdge.getIdArc());
493
                        second.setDirec(oldEdge.getDirec());
494
                        second.setType(oldEdge.getType());
495
                        second.setIdNodeOrig(idNode);
496
                        second.setIdNodeEnd(oldEdge.getIdNodeEnd());
497
                        graph.addEdge(second);
498

    
499

    
500
                        //////////////////////////////////////////////////////
501
                        // Ahora retocamos los enlaces que salen de cada nodo
502
                        //////////////////////////////////////////////////////
503
                        int i;
504
                        boolean encontrado = false;
505
                        for (i=0; i<pN1.getEnlaces().size(); i++)
506
                        {
507
                                GvEdge aux = (GvEdge) pN1.getEnlaces().get(i);
508
                                if (aux.getIdEdge() == idEdge)
509
                                {
510
                                        pN1.getEnlaces().set(i, first);
511
                                        encontrado = true;
512
                                        break;
513
                                }
514
                        } // for
515

    
516
                        newNode.getEnlaces().add(second);
517

    
518
        }
519

    
520
}
521

    
522