Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extGraph / src / org / gvsig / graph / core / NetworkUtils.java @ 40327

History | View | Annotate | Download (31.6 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 org.gvsig.graph.core;
42

    
43
import java.awt.Color;
44
import java.awt.geom.PathIterator;
45
import java.awt.geom.Point2D;
46
import java.awt.geom.Rectangle2D;
47
import java.io.File;
48
import java.io.FileNotFoundException;
49
import java.io.FileReader;
50
import java.util.ArrayList;
51
import java.util.Iterator;
52

    
53
import javax.swing.ImageIcon;
54

    
55
import org.apache.log4j.Logger;
56
import org.exolab.castor.xml.MarshalException;
57
import org.exolab.castor.xml.ValidationException;
58
import org.gvsig.exceptions.BaseException;
59
import org.gvsig.graph.solvers.Route;
60

    
61
import com.hardcode.gdbms.driver.exceptions.InitializeDriverException;
62
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
63
import com.iver.cit.gvsig.exceptions.layers.LegendLayerException;
64
import com.iver.cit.gvsig.fmap.MapControl;
65
import com.iver.cit.gvsig.fmap.ViewPort;
66
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
67
import com.iver.cit.gvsig.fmap.core.IFeature;
68
import com.iver.cit.gvsig.fmap.core.IGeometry;
69
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
70
import com.iver.cit.gvsig.fmap.core.styles.ArrowDecoratorStyle;
71
import com.iver.cit.gvsig.fmap.core.styles.ILineStyle;
72
import com.iver.cit.gvsig.fmap.core.styles.SimpleLineStyle;
73
import com.iver.cit.gvsig.fmap.core.symbols.IMarkerSymbol;
74
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
75
import com.iver.cit.gvsig.fmap.core.symbols.SimpleLineSymbol;
76
import com.iver.cit.gvsig.fmap.core.v02.FConstant;
77
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
78
import com.iver.cit.gvsig.fmap.core.v02.FSymbol;
79
import com.iver.cit.gvsig.fmap.drivers.BoundedShapes;
80
import com.iver.cit.gvsig.fmap.drivers.IFeatureIterator;
81
import com.iver.cit.gvsig.fmap.layers.FLayer;
82
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
83
import com.iver.cit.gvsig.fmap.layers.GraphicLayer;
84
import com.iver.cit.gvsig.fmap.layers.ReadableVectorial;
85
import com.iver.cit.gvsig.fmap.layers.XMLException;
86
import com.iver.cit.gvsig.fmap.rendering.FGraphic;
87
import com.iver.cit.gvsig.fmap.rendering.IVectorLegend;
88
import com.iver.cit.gvsig.fmap.rendering.LegendFactory;
89
import com.iver.cit.gvsig.fmap.spatialindex.ISpatialIndex;
90
import com.iver.cit.gvsig.fmap.spatialindex.QuadtreeJts;
91
import com.iver.utiles.XMLEntity;
92
import com.iver.utiles.xmlEntity.generate.XmlTag;
93
import com.vividsolutions.jts.geom.Coordinate;
94
import com.vividsolutions.jts.geom.CoordinateList;
95
import com.vividsolutions.jts.geom.CoordinateSequences;
96
import com.vividsolutions.jts.geom.Geometry;
97
import com.vividsolutions.jts.geom.GeometryFactory;
98
import com.vividsolutions.jts.geom.LineSegment;
99
import com.vividsolutions.jts.geom.LineString;
100
import com.vividsolutions.jts.geom.MultiPoint;
101
import com.vividsolutions.jts.geom.Point;
102
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
103

    
104
public class NetworkUtils {
105
        static int idSymbolFlag = -1;
106
        
107
        static Logger logger = Logger.getLogger(NetworkUtils.class);
108

    
109
        static private GeometryFactory geomFactory = new GeometryFactory();
110

    
111
        private static IMarkerSymbol simFlag2;
112
        private static FSymbol simFlag;
113

    
114
        public static void clearBarriersFromGraphics(MapControl mc) {
115
                GraphicLayer graphics = mc.getMapContext().getGraphicsLayer();
116
                for (int i = graphics.getNumGraphics() - 1; i >= 0; i--) {
117
                        FGraphic aux = graphics.getGraphic(i);
118
                        if (aux.getTag() != null)
119
                                if (aux.getTag().equalsIgnoreCase("BARRIER"))
120
                                        graphics.removeGraphic(aux);
121
                }
122
        }
123

    
124
        public static void clearFlagsFromGraphics(MapControl mc) {
125
                GraphicLayer graphics = mc.getMapContext().getGraphicsLayer();
126
                for (int i = graphics.getNumGraphics() - 1; i >= 0; i--) {
127
                        FGraphic aux = graphics.getGraphic(i);
128
                        if (aux.getTag() != null)
129
                                if (aux.getTag().equalsIgnoreCase("FLAG"))
130
                                        graphics.removeGraphic(aux);
131
                }
132
        }
133

    
134
        public static void clearFlagFromGraphics(MapControl mc, GvFlag flag) {
135
                GraphicLayer graphics = mc.getMapContext().getGraphicsLayer();
136
                FGraphic graphic = graphics.getGraphicByObjectTag(flag);
137
                graphics.removeGraphic(graphic);
138
        }
139

    
140
        public static void clearGraphicByObjectTag(MapControl mc, Object obj) {
141
                GraphicLayer graphics = mc.getMapContext().getGraphicsLayer();
142
                FGraphic graphic = graphics.getGraphicByObjectTag(obj);
143
                graphics.removeGraphic(graphic);
144
        }
145

    
146
        public static void clearRouteFromGraphics(MapControl mc) {
147
                GraphicLayer graphics = mc.getMapContext().getGraphicsLayer();
148
                for (int i = graphics.getNumGraphics() - 1; i >= 0; i--) {
149
                        FGraphic aux = graphics.getGraphic(i);
150
                        if (aux.getTag() != null)
151
                                if (aux.getTag().equalsIgnoreCase("ROUTE"))
152
                                        graphics.removeGraphic(aux);
153
                }
154
        }
155

    
156
        public static void centerGraphicsOnFlags(MapControl mc, GvFlag[] flags) {
157
                ViewPort vp = mc.getViewPort();
158
                Rectangle2D extent = vp.getAdjustedExtent();
159
                /*
160
                 * double xNC = flag.getOriginalPoint().getX(); double yNC =
161
                 * flag.getOriginalPoint().getY();
162
                 */
163
                double width = extent.getWidth();
164
                double height = extent.getHeight();
165

    
166
                Rectangle2D.Double r = null;// new Rectangle2D.Double();
167

    
168
                /*
169
                 * r.width = width; r.height = height; r.x = xNC - width/2; r.y = yNC -
170
                 * height/2;
171
                 */
172

    
173
                for (int i = 0; i < flags.length; i++) {
174
                        if (flags[i] != null) {
175
                                Point2D p = flags[i].getOriginalPoint();
176
                                if (r == null)
177
                                        r = new Rectangle2D.Double(p.getX(), p.getY(), 0, 0);
178
                                else
179
                                        r.add(flags[i].getOriginalPoint());
180
                        }
181
                }
182

    
183
                double realTol = mc.getViewPort().toMapDistance(15);
184

    
185
                r.height = r.height + realTol;
186
                r.width = r.width + realTol;
187
                r.x = r.x - (realTol / 2.0);// r.getMaxX() - r.width/2;
188
                r.y = r.y - (realTol / 2.0);// r.getMaxY() - r.height/2;
189

    
190
                vp.setExtent(r);
191
                mc.getMapContext().invalidate();
192
        }
193

    
194
        public static void centerGraphicsOnFlag(MapControl mc, GvFlag flag) {
195
                ViewPort vp = mc.getViewPort();
196
                Rectangle2D extent = vp.getAdjustedExtent();
197
                double xNC = flag.getOriginalPoint().getX();
198
                double yNC = flag.getOriginalPoint().getY();
199
                double width = extent.getWidth();
200
                double height = extent.getHeight();
201

    
202
                Rectangle2D.Double r = new Rectangle2D.Double();
203

    
204
                r.width = width;
205
                r.height = height;
206
                r.x = xNC - width / 2;
207
                r.y = yNC - height / 2;
208

    
209
                vp.setExtent(r);
210
        }
211

    
212
        public static void drawRouteOnGraphics(MapControl mc, Route route) {
213
                Iterator it = route.getFeatureList().iterator();
214
                int idSymbolLine = -1;
215
                GraphicLayer graphicLayer = mc.getMapContext().getGraphicsLayer();
216
                // if (idSymbolLine == -1)
217
                {
218
                        SimpleLineSymbol arrowSymbol = new SimpleLineSymbol();
219
                        // FSymbol arrowSymbol = new FSymbol(FConstant.SYMBOL_TYPE_LINE);
220
                        arrowSymbol.setLineColor(Color.RED);
221
                        arrowSymbol.setUnit(-1); // pixels
222
                        arrowSymbol.setLineWidth(3.0f);
223
                        ILineStyle lineStyle = new SimpleLineStyle();
224

    
225
                        ArrowDecoratorStyle arrowDecoratorStyle = new ArrowDecoratorStyle();
226
                        arrowDecoratorStyle.setArrowMarkerCount(1);
227
                        lineStyle.setArrowDecorator(arrowDecoratorStyle);
228
                        lineStyle.setLineWidth(3.0f);
229
                        arrowSymbol.setLineStyle(lineStyle);
230
                        idSymbolLine = graphicLayer.addSymbol(arrowSymbol);
231

    
232
                }
233
                // Para evitar hacer reallocate de los elementos de la
234
                // graphicList cada vez, creamos primero la lista
235
                // y la insertamos toda de una vez.
236
                ArrayList graphicsRoute = new ArrayList();
237
                while (it.hasNext()) {
238
                        IFeature feat = (IFeature) it.next();
239
                        IGeometry gAux = feat.getGeometry();
240
                        FGraphic graphic = new FGraphic(gAux, idSymbolLine);
241
                        graphic.setTag("ROUTE");
242
                        graphicsRoute.add(graphic);
243
                        // graphicLayer.insertGraphic(0, graphic);
244
                }
245
                // Lo insertamos al principio de la lista para que los
246
                // pushpins se dibujen despu?s.
247

    
248
                graphicLayer.inserGraphics(0, graphicsRoute);
249
                mc.drawGraphics();
250
        }
251

    
252
        public static File getNetworkFile(FLayer lyr) {
253
                String directoryName = System.getProperty("java.io.tmpdir");
254
                String aux = lyr.getName().replaceAll("\\Q.shp\\E", ".net");
255
                File newFile = new File(directoryName + File.separator + aux);
256
                return newFile;
257

    
258
        }
259

    
260
        public static void addGraphicFlag(MapControl mapControl, GvFlag flag) {
261
                addGraphicFlag(mapControl, flag, getDefaultSymbolFlag());
262
        }
263

    
264
        /**
265
         * @return
266
         */
267
        public static ISymbol getDefaultSymbolFlag() {
268
                if (simFlag == null) {
269

    
270
                        simFlag = new FSymbol(FConstant.SYMBOL_TYPE_ICON);
271
                        ImageIcon icon = new ImageIcon(NetworkUtils.class.getClassLoader()
272
                                        .getResource("images/pushpin.png"));
273
                        simFlag.setIcon(icon.getImage());
274
                        simFlag.setSize(24);
275
                        simFlag.setSizeInPixels(true);
276
                        simFlag.setStyle(FConstant.SYMBOL_STYLE_MARKER_IMAGEN);
277
                }
278
                return simFlag;
279
        }
280

    
281
        public static void addGraphicFlag(MapControl mapControl, GvFlag flag,
282
                        ISymbol sym) {
283
                GraphicLayer graphicLayer = mapControl.getMapContext()
284
                                .getGraphicsLayer();
285
                int idSymbol = graphicLayer.getSymbol(sym);
286
                if (idSymbol == -1) { // El s?mbolo no existe todav?a en la lista de
287
                        // gr?ficos
288
                        idSymbol = graphicLayer.addSymbol(sym);
289
                }
290
                IGeometry gAux = ShapeFactory.createPoint2D(flag.getOriginalPoint()
291
                                .getX(), flag.getOriginalPoint().getY());
292
                FGraphic graphic = new FGraphic(gAux, idSymbol);
293
                graphic.setTag("FLAG");
294
                graphic.setObjectTag(flag);
295
                graphicLayer.addGraphic(graphic);
296

    
297
        }
298

    
299
        public static double getPercentAlong(Geometry jtsGeom, double x, double y) {
300
                // Primero calculamos la longitud total del shape.
301
                // Luego calculamos el punto m?s cercano y su distancia para cada
302
                // segmento del shape.
303
                // Nos quedamos con el que est? m?s cerca y luego recorremos hasta ?l
304
                // acumulando distancia.
305
                // Finalmente, dividimos esa distancia por la longitud total.
306

    
307
                Coordinate[] coords = jtsGeom.getCoordinates();
308

    
309
                Coordinate userCoord = new Coordinate(x, y);
310

    
311
                double longReal = 0;
312
                // Le pegamos una primera pasada para saber su longitud real.
313
                // OJO, NO TRABAJAMOS CON SHAPES MULTIPARTE, NO TIENE SENTIDO CON LAS
314
                // REDES (CREO)
315
                // POR ESO SUPONEMOS UNA ?NICA PARTE (L?NEA CONT?NUA)
316
                // A la vez calculamos el punto m?s cercano y su distancia para cada
317
                // segmento.
318
                double minDist = Double.MAX_VALUE;
319
                double distTo = 0;
320
                double dist = 0;
321
                Coordinate cOrig = null;
322
                Coordinate closestPoint = null;
323
                for (int j = 0; j < coords.length - 1; j++) {
324
                        Coordinate c1 = coords[j];
325
                        Coordinate c2 = coords[j + 1];
326
                        LineSegment line = new LineSegment(c1, c2);
327

    
328
                        Coordinate auxPoint = line.closestPoint(userCoord);
329
                        dist = userCoord.distance(auxPoint);
330
                        if ((dist < minDist)) {
331
                                minDist = dist;
332
                                cOrig = c1;
333
                                closestPoint = auxPoint;
334
                                distTo = longReal;
335
                        }
336
                        longReal += line.getLength();
337
                }
338
                dist = cOrig.distance(closestPoint);
339
                double longBuscada = distTo + dist;
340

    
341
                double pct;
342
                if (longReal > 0)
343
                        pct = longBuscada / longReal;
344
                else
345
                        pct = 0.0;
346

    
347
                return pct;
348
        }
349

    
350
        /**
351
         * Receives jtsgeom, percentage of desired linestring and direction.
352
         * 
353
         * @param geom
354
         * @param pct
355
         * @param direction
356
         *            1=> same as geometry. 0=> Inversed
357
         * @return partial linestring
358
         */
359
        public static LineString getPartialLineString(Geometry geom, double pct,
360
                        int direction)
361
        // Si parte vale cero, los v?lidos son los primeros. Si no, los segundos.
362
        {
363
                int j, numVertices;
364
                double longAcum, longReal, longBuscada, distSobre, miniPorcentaje;
365
                double nuevaX, nuevaY; // Por cuestiones de claridad al programar
366
                double dist = 0;
367

    
368
                longAcum = 0;
369
                longReal = geom.getLength();
370
                longBuscada = longReal * pct;
371
                Coordinate[] coords = geom.getCoordinates();
372
                Coordinate c1 = null, c2 = null;
373
                ArrayList savedCoords = new ArrayList();
374
                Coordinate lastCoord = null;
375

    
376
                if (direction > 0) // Hemos entrado por el 1 hacia el 2 (al 2 no
377
                // llegamos)
378
                {
379
                        for (j = 0; j < coords.length - 1; j++) {
380
                                c1 = coords[j];
381
                                c2 = coords[j + 1];
382
                                dist = c1.distance(c2);
383
                                longAcum += dist;
384
                                if ((lastCoord == null) || (!c1.equals2D(lastCoord))) {
385
                                        savedCoords.add(c1);
386
                                        lastCoord = c1;
387
                                }
388

    
389
                                if (longAcum >= longBuscada) {
390
                                        // Hasta aqu?. Ahora ahi que poner el punto sobre el tramo
391
                                        distSobre = dist - (longAcum - longBuscada);
392
                                        miniPorcentaje = distSobre / dist;
393

    
394
                                        nuevaX = c1.x + (c2.x - c1.x) * miniPorcentaje;
395
                                        nuevaY = c1.y + (c2.y - c1.y) * miniPorcentaje;
396

    
397
                                        savedCoords.add(new Coordinate(nuevaX, nuevaY));
398
                                        break;
399
                                } // if longAcum >= longBuscada
400
                        } // for j
401

    
402
                } else // Hemos entrado por el 2 hacia el 1
403
                {
404
                        numVertices = 0;
405
                        for (j = 0; j < coords.length; j++) {
406
                                // //////////////////////////////////////////////////////////////
407
                                // 13_ene_2005: Si el ?ltimo punto es el ?ltimo punto no
408
                                // podemos acceder al elemento j+1 porque nos salimos del shape
409
                                // ///////////////////////////////////////////////////////////////
410
                                c1 = coords[j];
411
                                if (j < coords.length - 1) {
412
                                        c2 = coords[j + 1];
413

    
414
                                        dist = c1.distance(c2);
415
                                        longAcum += dist;
416
                                }
417

    
418
                                if (longAcum >= longBuscada) {
419
                                        // Hasta aqu?. Empezamos a meter puntos
420

    
421
                                        if (numVertices == 0) {
422
                                                distSobre = dist - (longAcum - longBuscada);
423
                                                miniPorcentaje = distSobre / dist;
424
                                                nuevaX = c1.x + (c2.x - c1.x) * miniPorcentaje;
425
                                                nuevaY = c1.y + (c2.y - c1.y) * miniPorcentaje;
426

    
427
                                                savedCoords.add(new Coordinate(nuevaX, nuevaY));
428
                                                savedCoords.add(c2);
429
                                        } else {
430
                                                if ((lastCoord == null) || (!c2.equals2D(lastCoord))) {
431
                                                        savedCoords.add(c2);
432
                                                        lastCoord = c2;
433
                                                }
434

    
435
                                        }
436
                                        numVertices++;
437
                                        // break;
438
                                } // if longAcum >= longBuscada
439
                        } // for j
440

    
441
                        // savedCoords.add(c2);
442

    
443
                } // if else
444

    
445
                return geomFactory.createLineString((Coordinate[]) savedCoords
446
                                .toArray(new Coordinate[0]));
447
        }
448

    
449
        
450
        
451
        /**
452
         * If coordList != null, it will be used to return all coordinates. Useful to avoid
453
         * two iterations, and only if you linestring is single part.
454
         * If you don't need it, simply set coordList = null
455
         * @param geom
456
         * @param coordList
457
         * @return
458
         */
459
        public static double getLength(IGeometry geom, ArrayList<Coordinate> coordList) {
460
                double partlength = 0;
461
                PathIterator pi = geom.getPathIterator(null, FConverter.FLATNESS);
462
                double[] theData = new double[6];
463
                double totalLength = 0;
464
                Coordinate c1 = null;
465
                Coordinate c2 = null;
466
                Coordinate first = null;
467
                while (!pi.isDone()) {
468
                        //while not done
469
                        int type = pi.currentSegment(theData);
470
                switch (type)
471
                {
472
                case PathIterator.SEG_MOVETO:
473
//                        coordList = new CoordinateList();
474
//                        listOfParts.add(coordList);
475
                        totalLength += partlength;
476
                        partlength = 0;
477
                        c1= new Coordinate(theData[0], theData[1]);
478
                        first = c1;
479
                        if (coordList != null)
480
                                coordList.add(c1);
481
                        break;
482
                case PathIterator.SEG_LINETO:
483
                        c2= new Coordinate(theData[0], theData[1]);
484
                        if (coordList != null)
485
                                coordList.add(c2);
486
                        partlength += c2.distance(c1);
487
                        c1 = c2;
488
                        break;
489

    
490
                case PathIterator.SEG_CLOSE:
491
                        if (coordList != null)
492
                                coordList.add(first);
493
                        partlength += c1.distance(first);
494
                        break;
495

    
496
                }
497
                pi.next();
498
                }
499
                totalLength += partlength;
500
                return totalLength;
501
        }
502
        
503
        public static IGeometry flipGeometry(IGeometry geom) {
504
                GeneralPathX gp = new GeneralPathX();
505
                PathIterator pi = geom.getPathIterator(null, FConverter.FLATNESS);
506
                double[] theData = new double[6];
507
        Coordinate first = null;
508
        CoordinateList coordList = new CoordinateList();
509
        Coordinate c1;
510
        GeneralPathX newGp = new GeneralPathX();
511
        ArrayList listOfParts = new ArrayList();
512
                while (!pi.isDone()) {
513
                        //while not done
514
                        int type = pi.currentSegment(theData);
515
                switch (type)
516
                {
517
                case PathIterator.SEG_MOVETO:
518
                        coordList = new CoordinateList();
519
                        listOfParts.add(coordList);
520
                        c1= new Coordinate(theData[0], theData[1]);
521
                        coordList.add(c1, true);
522
                        break;
523
                case PathIterator.SEG_LINETO:
524
                        c1= new Coordinate(theData[0], theData[1]);
525
                        coordList.add(c1, true);
526
                        break;
527

    
528
                case PathIterator.SEG_CLOSE:
529
                        coordList.add(coordList.getCoordinate(0));
530
                        break;
531

    
532
                }
533
                pi.next();
534
                }
535

    
536
                for (int i=listOfParts.size()-1; i>=0; i--)
537
                {
538
                        coordList = (CoordinateList) listOfParts.get(i);
539
                        Coordinate[] coords = coordList.toCoordinateArray();
540
                        CoordinateArraySequence seq = new CoordinateArraySequence(coords);
541
                        CoordinateSequences.reverse(seq);
542
                        coords = seq.toCoordinateArray();
543
                        newGp.moveTo(coords[0].x, coords[0].y);
544
                        for (int j=1; j < coords.length; j++)
545
                        {
546
                                newGp.lineTo(coords[j].x, coords[j].y);
547
                        }
548
                }
549
                
550
                return ShapeFactory.createPolyline2D(newGp);
551
        }
552
        
553
        
554
        /**
555
         * Receives IGeometry, percentage of desired linestring and direction.
556
         * Used in populateRoute (at least) in order to speed up populate route
557
         * 
558
         * @param geom
559
         * @param pct
560
         * @param direction
561
         *            1=> same as geometry. 0=> Inversed
562
         * @return partial linestring
563
         */
564
        public static IGeometry getPartialLineString(IGeometry geom, double pct,
565
                        int direction)
566
        // Si parte vale cero, los v?lidos son los primeros. Si no, los segundos.
567
        {
568
                int j, numVertices;
569
                double longAcum, longReal, longBuscada, distSobre, miniPorcentaje;
570
                double nuevaX, nuevaY; // Por cuestiones de claridad al programar
571
                double dist = 0;
572

    
573
                longAcum = 0;
574
                ArrayList<Coordinate> coords = new ArrayList<Coordinate>();
575
                longReal = getLength(geom, coords);
576
                longBuscada = longReal * pct;
577
//                Coordinate[] coords = geom.getCoordinates();
578
                Coordinate c1 = null, c2 = null;
579
//                ArrayList savedCoords = new ArrayList();
580
                GeneralPathX gpx = new GeneralPathX();
581
                Coordinate lastCoord = null;
582

    
583
                if (direction > 0) // Hemos entrado por el 1 hacia el 2 (al 2 no
584
                // llegamos)
585
                {
586
                        numVertices = 0;
587
                        for (j = 0; j < coords.size() - 1; j++) {
588
                                c1 = coords.get(j);
589
                                c2 = coords.get(j + 1);
590
                                dist = c1.distance(c2);
591
                                longAcum += dist;
592
                                if ((lastCoord == null) || (!c1.equals2D(lastCoord))) {
593
//                                        savedCoords.add(c1);
594
                                        if (numVertices == 0)
595
                                                gpx.moveTo(c1.x, c1.y);
596
                                        else
597
                                                gpx.lineTo(c1.x, c1.y);
598
                                        numVertices++;
599
                                        lastCoord = c1;
600
                                }
601

    
602
                                if (longAcum >= longBuscada) {
603
                                        // Hasta aqu?. Ahora ahi que poner el punto sobre el tramo
604
                                        distSobre = dist - (longAcum - longBuscada);
605
                                        miniPorcentaje = distSobre / dist;
606

    
607
                                        nuevaX = c1.x + (c2.x - c1.x) * miniPorcentaje;
608
                                        nuevaY = c1.y + (c2.y - c1.y) * miniPorcentaje;
609

    
610
//                                        savedCoords.add(new Coordinate(nuevaX, nuevaY));
611
                                        gpx.lineTo(nuevaX, nuevaY);
612
                                        numVertices++;
613
                                        break;
614
                                } // if longAcum >= longBuscada
615
                        } // for j
616

    
617
                } else // Hemos entrado por el 2 hacia el 1
618
                {
619
                        numVertices = 0;
620
                        for (j = 0; j < coords.size(); j++) {
621
                                // //////////////////////////////////////////////////////////////
622
                                // 13_ene_2005: Si el ?ltimo punto es el ?ltimo punto no
623
                                // podemos acceder al elemento j+1 porque nos salimos del shape
624
                                // ///////////////////////////////////////////////////////////////
625
                                c1 = coords.get(j);
626
                                if (j < coords.size() - 1) {
627
                                        c2 = coords.get(j + 1);
628

    
629
                                        dist = c1.distance(c2);
630
                                        longAcum += dist;
631
                                }
632

    
633
                                if (longAcum >= longBuscada) {
634
                                        // Hasta aqu?. Empezamos a meter puntos
635

    
636
                                        if (numVertices == 0) {
637
                                                distSobre = dist - (longAcum - longBuscada);
638
                                                miniPorcentaje = distSobre / dist;
639
                                                nuevaX = c1.x + (c2.x - c1.x) * miniPorcentaje;
640
                                                nuevaY = c1.y + (c2.y - c1.y) * miniPorcentaje;
641

    
642
//                                                savedCoords.add(new Coordinate(nuevaX, nuevaY));
643
//                                                savedCoords.add(c2);
644
                                                gpx.moveTo(nuevaX, nuevaY);
645
                                                gpx.lineTo(c2.x, c2.y);
646
                                        } else {
647
                                                if ((lastCoord == null) || (!c2.equals2D(lastCoord))) {
648
//                                                        savedCoords.add(c2);
649
                                                        gpx.lineTo(c2.x, c2.y);
650
                                                        lastCoord = c2;
651
                                                }
652

    
653
                                        }
654
                                        numVertices++;
655
                                        // break;
656
                                } // if longAcum >= longBuscada
657
                        } // for j
658

    
659
                        // savedCoords.add(c2);
660

    
661
                } // if else
662

    
663
                return ShapeFactory.createPolyline2D(gpx);
664
        }
665
        
666
        
667
        /**
668
         * Retrieves a sub-linestring from pct1 and length = pct2 
669
         * 
670
         * @param geom
671
         * @param pct1 =>
672
         *            from pct
673
         * @param pct2 => distance (in percentage) of second point
674
         * @param direction
675
         *            1=> same as geometry. 0=> Inversed
676
         * @return partial linestring
677
         */
678
        public static LineString getPartialLineString(Geometry geom, double pct1,
679
                        double pct2, int direction)
680
        // Si parte vale cero, los v?lidos son los primeros. Si no, los segundos.
681
        {
682
                int j, numVertices;
683
                double longAcum, longReal, longFrom, longTo, distSobre, miniPorcentaje;
684
                double nuevaX, nuevaY; // Por cuestiones de claridad al programar
685
                double dist = 0;
686

    
687
                longAcum = 0;
688
                longReal = geom.getLength();
689
                longFrom = longReal * pct1;
690
                
691
                Coordinate[] coords = geom.getCoordinates();
692
                Coordinate c1 = null, c2 = null;
693
                ArrayList savedCoords = new ArrayList();
694
                Coordinate lastCoord = null;
695

    
696
                if (direction > 0) // Hemos entrado por el 1 hacia el 2 (al 2 no
697
                // llegamos)
698
                {
699
                        longTo = longReal * pct2; //longReal * (pct1 + pct2);
700
                        numVertices = 0;
701
                        for (j = 0; j < coords.length - 1; j++) {
702
                                c1 = coords[j];
703
                                c2 = coords[j + 1];
704
                                dist = c1.distance(c2);
705
                                longAcum += dist;
706
                                if ((lastCoord == null) || (!c1.equals2D(lastCoord))) {
707
                                        if (longAcum >= longFrom) {
708
                                                if (numVertices == 0) {
709
                                                        distSobre = dist - (longAcum - longFrom);
710
                                                        miniPorcentaje = distSobre / dist;
711
                                                        nuevaX = c1.x + (c2.x - c1.x) * miniPorcentaje;
712
                                                        nuevaY = c1.y + (c2.y - c1.y) * miniPorcentaje;
713

    
714
                                                        savedCoords.add(new Coordinate(nuevaX, nuevaY));
715
                                                } else {
716
                                                        savedCoords.add(c1);
717
                                                }
718
                                                numVertices++;
719
                                        }
720
                                        lastCoord = c1;
721
                                }
722

    
723
                                if (longAcum >= longTo) {
724
                                        // Hasta aqu?. Ahora ahi que poner el punto sobre el tramo
725
                                        distSobre = dist - (longAcum - longTo);
726
                                        miniPorcentaje = distSobre / dist;
727

    
728
                                        nuevaX = c1.x + (c2.x - c1.x) * miniPorcentaje;
729
                                        nuevaY = c1.y + (c2.y - c1.y) * miniPorcentaje;
730

    
731
                                        savedCoords.add(new Coordinate(nuevaX, nuevaY));
732
                                        break;
733
                                } // if longAcum >= longBuscada
734
                        } // for j
735

    
736
                } else // Hemos entrado por el 2 hacia el 1
737
                {
738
                        numVertices = 0;
739
                        
740
                        longTo = longFrom;
741
                        longFrom = longFrom - (longReal * pct2);
742

    
743
                        for (j = 0; j < coords.length; j++) {
744
                                // //////////////////////////////////////////////////////////////
745
                                // 13_ene_2005: Si el ?ltimo punto es el ?ltimo punto no
746
                                // podemos acceder al elemento j+1 porque nos salimos del shape
747
                                // ///////////////////////////////////////////////////////////////
748
                                c1 = coords[j];
749
                                if (j < coords.length - 1) {
750
                                        c2 = coords[j + 1];
751

    
752
                                        dist = c1.distance(c2);
753
                                        longAcum += dist;
754
                                }
755

    
756
                                if (longAcum >= longFrom) {
757
                                        // Desde aqu?. Empezamos a meter puntos
758

    
759
                                        if (numVertices == 0) {
760
                                                distSobre = dist - (longAcum - longFrom);
761
                                                miniPorcentaje = distSobre / dist;
762
                                                nuevaX = c1.x + (c2.x - c1.x) * miniPorcentaje;
763
                                                nuevaY = c1.y + (c2.y - c1.y) * miniPorcentaje;
764

    
765
                                                savedCoords.add(new Coordinate(nuevaX, nuevaY));
766
                                                savedCoords.add(c2);
767
                                        } else {
768
                                                if ((lastCoord == null) || (!c2.equals2D(lastCoord))) {
769
                                                        if (longAcum <= longTo)
770
                                                                savedCoords.add(c2);
771
                                                        lastCoord = c2;
772
                                                }
773

    
774
                                        }
775
                                        numVertices++;
776
                                        if (longAcum >= longTo) {
777
                                                // Hasta aqu?. Ahora ahi que poner el punto sobre el
778
                                                // tramo
779
                                                distSobre = dist - (longAcum - longTo);
780
                                                miniPorcentaje = distSobre / dist;
781

    
782
                                                nuevaX = c1.x + (c2.x - c1.x) * miniPorcentaje;
783
                                                nuevaY = c1.y + (c2.y - c1.y) * miniPorcentaje;
784

    
785
                                                savedCoords.add(new Coordinate(nuevaX, nuevaY));
786
                                                break;
787
                                        } // if longAcum >= longTo
788

    
789
                                } // if longAcum >= longFrom
790
                        } // for j
791

    
792
                        // savedCoords.add(c2);
793

    
794
                } // if else
795

    
796
                if (savedCoords.size() < 2) {
797
                        Coordinate[] cero = new Coordinate[2];
798
                        cero[0] = (Coordinate) savedCoords.get(0);
799
                        cero[1] = (Coordinate) savedCoords.get(0);
800
                        return geomFactory.createLineString(cero);
801
                }
802
                return geomFactory.createLineString((Coordinate[]) savedCoords
803
                                .toArray(new Coordinate[0]));
804
        }
805

    
806
        public static double[] string2doubleArray(String str, String separator)
807
                        throws NumberFormatException {
808
                str = str.replace(" ", "");
809

    
810
                if (!str.contains(separator)) {
811
                        try {
812
                                double[] result = new double[1];
813
                                result[0] = Double.parseDouble(str);
814
                                return result;
815
                        } catch (NumberFormatException except) {
816
                                if (str.startsWith("[") && str.endsWith("]")) {
817
                                        String[] tokens = str.substring(1, str.length() - 1).split(
818
                                                        ":");
819
                                        if (tokens.length == 3) {
820
                                                try {
821
                                                        Double ini = Double.valueOf(tokens[0]);
822
                                                        Double end = Double.valueOf(tokens[1]);
823
                                                        Double interval = Double.valueOf(tokens[2]);
824

    
825
                                                        int length = ((int) ((end - ini) / interval)) + 1;
826
                                                        if (length > 0) {
827
                                                                double[] result = new double[length];
828

    
829
                                                                for (int i = 0; i < result.length; i++) {
830
                                                                        result[i] = ini;
831
                                                                        ini += interval;
832
                                                                }
833

    
834
                                                                return result;
835
                                                        } else {
836
                                                                return new double[0];
837
                                                        }
838
                                                } catch (NumberFormatException except2) {
839
                                                        throw except2;
840
                                                }
841
                                        } else {
842
                                                throw except;
843
                                        }
844
                                } else {
845
                                        throw except;
846
                                }
847
                        }
848
                } else {
849
                        String[] parts;
850
                        parts = str.split(separator);
851
                        ArrayList ret = new ArrayList();
852

    
853
                        for (int i = 0; i < parts.length; i++) {
854
                                try {
855
                                        ret.add(Double.valueOf(parts[i]));
856
                                } catch (NumberFormatException except) {
857
                                        if (parts[i].startsWith("[") && parts[i].endsWith("]")) {
858
                                                String[] tokens = parts[i].substring(1,
859
                                                                parts[i].length() - 1).split(":");
860
                                                if (tokens.length == 3) {
861
                                                        try {
862
                                                                Double ini = Double.valueOf(tokens[0]);
863
                                                                Double end = Double.valueOf(tokens[1]);
864
                                                                Double interval = Double.valueOf(tokens[2]);
865

    
866
                                                                for (double j = ini; j <= end; j += interval) {
867
                                                                        ret.add(Double.valueOf(j));
868
                                                                }
869
                                                        } catch (NumberFormatException except2) {
870
                                                                throw except2;
871
                                                        }
872
                                                }
873
                                        } else {
874
                                                throw except;
875
                                        }
876
                                }
877
                        }
878

    
879
                        double[] result = new double[ret.size()];
880
                        for (int i = 0; i < result.length; i++) {
881
                                result[i] = ((Double) ret.get(i)).doubleValue();
882
                        }
883

    
884
                        return result;
885
                }
886
        }
887

    
888
        /**
889
         * Truco sucio para evitar la inquisici?n. Cuando funcione, habr? que hacer
890
         * una propuesta para ver si es aceptado....
891
         * 
892
         * @param mapCtrl
893
         * @param x
894
         * @param y
895
         */
896
        public static void flashPoint(MapControl mapCtrl, double x, double y) {
897
                flashPoint(mapCtrl, Color.RED, 5, x, y);
898
        }
899

    
900
        /**
901
         * @param mapCtrl
902
         * @param color
903
         * @param x
904
         * @param y
905
         */
906
        public static void flashPoint(MapControl mapCtrl, Color color,
907
                        int maxCount, double x, double y) {
908
                int delay = 100; // milliseconds
909
                MyTask task = new MyTask(mapCtrl, color, maxCount, x, y);
910

    
911
                java.util.Timer timer = new java.util.Timer();
912
                timer.schedule(task, delay, 60);
913

    
914
        }
915

    
916
        public static GvFlag[] putFlagsOnNetwork(FLyrVect layer, Network net,
917
                        double tolerance) throws BaseException {
918
                ReadableVectorial reader = layer.getSource();
919
                reader.start();
920
                IFeatureIterator it = reader.getFeatureIterator();
921
                int i = 0;
922
                ArrayList<GvFlag> flags = new ArrayList();
923
                while (it.hasNext()) {
924
                        IFeature feat = it.next();
925
                        Geometry geo = feat.getGeometry().toJTSGeometry();
926
                        if (!((geo instanceof Point) || (geo instanceof MultiPoint)))
927
                                continue;
928

    
929
                        Coordinate[] coords = geo.getCoordinates();
930
                         if (coords.length > 1) {
931
                                 logger.warn("The record " + i + " has " + coords.length + "coordinates. Pay attention!!");
932
                                 logger.warn("Only one point will be used.");
933
                         }
934
                        for (int j = 0; j < coords.length; j++) {
935
                                GvFlag flag = net.addFlag(coords[j].x, coords[j].y, tolerance);
936
                                if (flag == null) {
937
                                        GraphException e = new GraphException("Punto " + i
938
                                                        + " fuera de la red. Tolerancia=" + tolerance);
939
                                        e.setCode(GraphException.FLAG_OUT_NETWORK);
940
                                        throw e;
941
                                        // NotificationManager.addError("No se puedo situar el
942
                                        // registro " + i +
943
                                        // " Por favor, compruebe que est? encima de la red o
944
                                        // aumente la tolerancia.",
945
                                        // e);
946
                                }
947
                                System.out.println("Situando flag " + i + " de la capa " + layer.getName() + " en idArc=" + flag.getIdArc());
948
                                flags.add(flag);
949
                                flag.getProperties().put("rec", new Integer(i));
950
                                break;
951
                        }
952
                        i++;
953
                }
954
                it.closeIterator();
955
                reader.stop();
956
                return flags.toArray(new GvFlag[0]);
957
        }
958
        
959
        /**
960
         * Parche hasta corregir QuadtreGT2 y createSpatialIndex (lo de menos de
961
         * 65.000 niveles)
962
         * 
963
         * @param lyrVect
964
         * @throws ReadDriverException 
965
         * @throws InitializeDriverException 
966
         */
967
        public static ISpatialIndex createJtsQuadtree(FLyrVect lyrVect) throws InitializeDriverException, ReadDriverException {
968
                ReadableVectorial va = lyrVect.getSource();
969
                if (!(va.getDriver() instanceof BoundedShapes))
970
                        return null;
971
                va.start();
972
                QuadtreeJts spatialIndex = new QuadtreeJts();
973
                BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
974
                int to = va.getShapeCount();
975
                for (int i = 0; i < to; i++) {
976
                        Rectangle2D r = shapeBounds.getShapeBounds(i);
977
                        if (r != null)
978
                                spatialIndex.insert(r, i);
979
                        if ((i % 100000) == 0) 
980
                                System.out.println("Inserting  " + i + " bounding of " + to);
981
                        
982
                } // for
983
                va.stop();
984
                // vectorial adapter needs a reference to the spatial index, to
985
                // solve
986
                // request for feature iteration based in spatial queries
987
                va.setSpatialIndex(spatialIndex);
988
                return spatialIndex;
989
        }
990

    
991
        public static void loadLegend(FLyrVect lyr, String gvlPath) {
992
                File xmlFile = new File(gvlPath);
993
                                
994
                FileReader reader = null;
995

    
996
                try {
997
                        reader = new FileReader(xmlFile);
998

    
999
                        XmlTag tag = (XmlTag) XmlTag.unmarshal(reader);
1000
                        IVectorLegend myLegend = LegendFactory.createFromXML(new XMLEntity(tag));
1001

    
1002
                        if(myLegend != null ) {
1003
                                lyr.setLegend(myLegend);
1004
                        }
1005
                } catch (FileNotFoundException e) {
1006
                        // TODO Auto-generated catch block
1007
                        e.printStackTrace();
1008
                } catch (MarshalException e) {
1009
                        // TODO Auto-generated catch block
1010
                        e.printStackTrace();
1011
                } catch (ValidationException e) {
1012
                        // TODO Auto-generated catch block
1013
                        e.printStackTrace();
1014
                } catch (XMLException e) {
1015
                        // TODO Auto-generated catch block
1016
                        e.printStackTrace();
1017
                } catch (LegendLayerException e) {
1018
                        // TODO Auto-generated catch block
1019
                        e.printStackTrace();
1020
                }
1021

    
1022
                
1023
        }
1024

    
1025

    
1026
}