Statistics
| Revision:

root / trunk / extensions / extGraph / src / org / gvsig / graph / solvers / ServiceAreaExtractor2_From_Branch.java @ 29800

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

    
42
// 18/09/2007 fjp
43
// @author: Fco. Jos? Pe?arrubia        fpenarru@gmail.com
44
package org.gvsig.graph.solvers;
45

    
46
import java.io.File;
47
import java.sql.Types;
48
import java.util.ArrayList;
49
import java.util.HashMap;
50
import java.util.HashSet;
51
import java.util.Iterator;
52
import java.util.Map;
53
import java.util.Set;
54

    
55
import org.gvsig.exceptions.BaseException;
56
import org.gvsig.fmap.algorithm.triangulation.visad.DelaunayWatson;
57
import org.gvsig.graph.core.GvEdge;
58
import org.gvsig.graph.core.GvNode;
59
import org.gvsig.graph.core.IGraph;
60
import org.gvsig.graph.core.Network;
61
import org.gvsig.graph.core.NetworkUtils;
62

    
63
import com.hardcode.gdbms.driver.exceptions.InitializeDriverException;
64
import com.hardcode.gdbms.driver.exceptions.InitializeWriterException;
65
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
66
import com.hardcode.gdbms.engine.values.Value;
67
import com.hardcode.gdbms.engine.values.ValueFactory;
68
import com.iver.cit.gvsig.fmap.core.DefaultFeature;
69
import com.iver.cit.gvsig.fmap.core.FShape;
70
import com.iver.cit.gvsig.fmap.core.IGeometry;
71
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
72
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
73
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
74
import com.iver.cit.gvsig.fmap.drivers.SHPLayerDefinition;
75
import com.iver.cit.gvsig.fmap.edition.DefaultRowEdited;
76
import com.iver.cit.gvsig.fmap.edition.IRowEdited;
77
import com.iver.cit.gvsig.fmap.edition.writers.shp.ShpWriter;
78
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
79
import com.iver.cit.gvsig.fmap.layers.LayerFactory;
80
import com.iver.cit.gvsig.fmap.layers.ReadableVectorial;
81
import com.vividsolutions.jts.algorithm.CGAlgorithms;
82
import com.vividsolutions.jts.algorithm.CentroidPoint;
83
import com.vividsolutions.jts.geom.Coordinate;
84
import com.vividsolutions.jts.geom.Geometry;
85
import com.vividsolutions.jts.geom.GeometryFactory;
86
import com.vividsolutions.jts.geom.LineString;
87
import com.vividsolutions.jts.geom.LinearRing;
88
import com.vividsolutions.jts.geom.Polygon;
89

    
90
/**
91
 * @author fjp
92
 * FROM BRANCH
93
 * 
94
 * This class can label nodes with distances and costs to a flag. You will
95
 * obtain a temp shp layer with fields IdArc, IdEdge, CostOrig, DistOrig,
96
 * CostEnd, DistEnd, IdFlag
97
 * 
98
 * La diferencia con ServiceAreaExtractor es que esta versi?n escucha al
99
 * algoritmo Dijkstra, y va montando el shp de l?neas conforme va siendo
100
 * explorada la red. La gran ventaja de hacerlo as? es que no dependes del
101
 * tama?o de la red. Solo recorres los tramos y nodos que exploras, de forma que
102
 * si limitas el ?rea de servicio a una distancia m?xima, la red solo se explora
103
 * hasta esa distancia / coste.
104
 * 
105
 */
106
public class ServiceAreaExtractor2_From_Branch implements IDijkstraListener {
107
        private static String tempDirectoryPath = System
108
                        .getProperty("java.io.tmpdir");
109

    
110
        static FieldDescription[] fields = new FieldDescription[7];
111
        static {
112
                FieldDescription fieldDesc = new FieldDescription();
113
                fieldDesc.setFieldName("IDARC");
114
                fieldDesc.setFieldType(Types.INTEGER);
115
                fieldDesc.setFieldLength(20);
116
                fieldDesc.setFieldDecimalCount(0);
117
                fields[0] = fieldDesc;
118

    
119
                fieldDesc = new FieldDescription();
120
                fieldDesc.setFieldName("IDEDGE");
121
                fieldDesc.setFieldType(Types.INTEGER);
122
                fieldDesc.setFieldLength(20);
123
                fieldDesc.setFieldDecimalCount(0);
124
                fields[1] = fieldDesc;
125

    
126
                fieldDesc = new FieldDescription();
127
                fieldDesc.setFieldName("COSTORIG");
128
                fieldDesc.setFieldType(Types.DOUBLE);
129
                fieldDesc.setFieldLength(20);
130
                fieldDesc.setFieldDecimalCount(5);
131
                fields[2] = fieldDesc;
132

    
133
                fieldDesc = new FieldDescription();
134
                fieldDesc.setFieldName("DISTORIG");
135
                fieldDesc.setFieldType(Types.DOUBLE);
136
                fieldDesc.setFieldLength(20);
137
                fieldDesc.setFieldDecimalCount(5);
138
                fields[3] = fieldDesc;
139

    
140
                fieldDesc = new FieldDescription();
141
                fieldDesc.setFieldName("COSTEND");
142
                fieldDesc.setFieldType(Types.DOUBLE);
143
                fieldDesc.setFieldLength(20);
144
                fieldDesc.setFieldDecimalCount(5);
145
                fields[4] = fieldDesc;
146

    
147
                fieldDesc = new FieldDescription();
148
                fieldDesc.setFieldName("DISTEND");
149
                fieldDesc.setFieldType(Types.DOUBLE);
150
                fieldDesc.setFieldLength(20);
151
                fieldDesc.setFieldDecimalCount(5);
152
                fields[5] = fieldDesc;
153

    
154
                fieldDesc = new FieldDescription();
155
                fieldDesc.setFieldName("IDFLAG");
156
                fieldDesc.setFieldType(Types.INTEGER);
157
                fieldDesc.setFieldLength(20);
158
                fieldDesc.setFieldDecimalCount(5);
159
                fields[6] = fieldDesc;
160

    
161
        }
162
        
163
        static FieldDescription[] fieldsPol = new FieldDescription[2];
164
        static {
165
                FieldDescription fieldDesc = new FieldDescription();
166
                fieldDesc.setFieldName("COST");
167
                fieldDesc.setFieldType(Types.DOUBLE);
168
                fieldDesc.setFieldLength(20);
169
                fieldDesc.setFieldDecimalCount(5);
170
                fieldsPol[0] = fieldDesc;
171
                
172
                fieldDesc = new FieldDescription();
173
                fieldDesc.setFieldName("IDFLAG");
174
                fieldDesc.setFieldType(Types.INTEGER);
175
                fieldDesc.setFieldLength(20);
176
                fieldDesc.setFieldDecimalCount(5);
177
                fieldsPol[1] = fieldDesc;
178

    
179
        }
180
        
181
        static GeometryFactory gf = new GeometryFactory();
182

    
183
        private class VisitedEdge {
184
                private GvEdge edge;
185
                private double percentcost;
186
                public VisitedEdge(GvEdge edge) {
187
                        this.edge = edge;
188
                        IGraph g = net.getGraph();
189
                        GvNode nOrig = g.getNodeByID(edge.getIdNodeOrig());
190
                        double maxCost = costs[costs .length-1];
191
                        double costCalculated = nOrig.getBestCost() + edge.getWeight();
192
                        
193
                        if (costCalculated < maxCost)
194
                                percentcost = 1.0;
195
                        else
196
                        {
197
                                double percentCostCalculated = (maxCost - nOrig.getBestCost())/ edge.getWeight();
198
                                percentcost = percentCostCalculated;
199
                        }
200
                        
201
                }
202
                public GvEdge getEdge() {
203
                        return edge;
204
                }
205
                public double getPercentcost() {
206
                        return percentcost;
207
                }
208
                public void setPercentCost(double d) {
209
                        this.percentcost = d;
210
                        
211
                }
212
        }
213

    
214
        private Network net;
215

    
216
        private ShpWriter shpWriter;
217
        private ShpWriter shpWriterPol;
218
        private ShpWriter shpWriterTri;
219
        private File fTempPol;
220
        private File fTempTri;
221
        private SHPLayerDefinition layerDefPol;
222
        private SHPLayerDefinition layerDefTri;
223
        
224
        
225
        private HashMap<String, VisitedEdge> visitedEdges = new HashMap();
226

    
227
        private File fTemp;
228

    
229
        private SHPLayerDefinition layerDef;
230

    
231
        private int idFlag;
232

    
233
        private ReadableVectorial adapter;
234

    
235
//        private double maxCost;
236

    
237
        private Geometry serviceArea;
238
        private ArrayList <Geometry> serviceAreaPolygons;
239

    
240
        private double[] costs = null;        
241
        
242
        private boolean bDoCompactArea = false;
243
        
244
        private ArrayList borderCoords = new ArrayList();
245

    
246
        private HashSet<Coordinate> nodes;
247
//        DelaunayFast tri2;
248
        DelaunayWatson tri2;
249

    
250
        /**
251
         * @param net
252
         * @throws Exception 
253
         * @throws InitializeWriterException
254
         * @throws ReadDriverException
255
         * @throws InitializeDriverException
256
         */
257
        public ServiceAreaExtractor2_From_Branch(Network net) throws Exception {
258
                this.net = net;
259
                int aux = (int) (Math.random() * 1000);
260
                
261
                nodes = new HashSet<Coordinate>();
262
                
263
                
264
                String nameLine = "tmpServiceAreaLine" + aux + ".shp";
265
                String namePol = "tmpServiceAreaPol" + aux + ".shp";
266
                String nameTri = "tmpTri" + aux + ".shp";
267
                fTemp = new File(tempDirectoryPath + "/" + nameLine );
268
                fTempPol = new File(tempDirectoryPath + "/" + namePol );
269
                fTempTri = new File(tempDirectoryPath + "/" + nameTri );
270
                
271
                layerDef = new SHPLayerDefinition();
272
                layerDef.setFile(fTemp);
273
                layerDef.setName(nameLine);                
274
                layerDef.setFieldsDesc(fields);
275
                layerDef.setShapeType(FShape.LINE);
276

    
277
                layerDefPol = new SHPLayerDefinition();
278
                layerDefPol.setFile(fTempPol);
279
                layerDefPol.setName(namePol);                
280
                layerDefPol.setFieldsDesc(fieldsPol);
281
                layerDefPol.setShapeType(FShape.POLYGON);
282

    
283
                layerDefTri = new SHPLayerDefinition();
284
                layerDefTri.setFile(fTempTri);
285
                layerDefTri.setName(nameTri);                
286
                layerDefTri.setFieldsDesc(fieldsPol);
287
                layerDefTri.setShapeType(FShape.POLYGON);
288
                
289
                shpWriter = new ShpWriter();
290
                shpWriter.setFile(fTemp);
291
                shpWriter.initialize(layerDef);
292

    
293
                shpWriterPol = new ShpWriter();
294
                shpWriterPol.setFile(fTempPol);
295
                shpWriterPol.initialize(layerDefPol);
296
                
297
                shpWriterTri = new ShpWriter();
298
                shpWriterTri.setFile(fTempTri);
299
                shpWriterTri.initialize(layerDefTri);
300
                
301
                shpWriter.preProcess();
302
                shpWriterPol.preProcess();
303
                shpWriterTri.preProcess();
304
                
305
                FLyrVect lyr = net.getLayer();
306
                adapter = lyr.getSource();
307
                adapter.start();
308
                
309
                serviceAreaPolygons = new ArrayList<Geometry>();
310

    
311
        }
312

    
313
        /**
314
         * Devuelve el ?ndice del intervalo m?s alto que contiene a ese valor.
315
         * @param bestCost
316
         * @param costs
317
         * @return
318
         */
319
        private int getCostInterval(double bestCost, double[] costs) {
320
                int ret = 0;
321
                if (bestCost > costs[costs.length-1])
322
                        return -1;
323
                for (int i=costs.length-1; i>=0; i--) {
324
                        if (bestCost > costs[i])
325
                        {
326
                                ret = i+1;
327
                                break;
328
                        }
329
                }
330
                return ret;
331
        }
332

    
333
        /**
334
         * We process each edge and prepare a list of polygons, classified by
335
         * cost
336
         * @param edge
337
         * @param nodeOrig
338
         * @param nodeEnd
339
         * @param geom
340
         * @param costs
341
         */
342
        private void processEdgeForPolygon(GvEdge edge, GvNode nodeOrig, GvNode nodeEnd, IGeometry geom, double[] costs) {
343
                if (nodeEnd.getBestCost() > nodeOrig.getBestCost())
344
                {                
345
                        // miramos en qu? pol?gono cae ese edge POR COMPLETO 
346
                        // El coste de su punto final es menor que uno de los costes.
347
                        int indexInterval = getCostInterval(nodeEnd.getBestCost(), costs);
348
                        // Un pol?gono por cada zona
349
                        Geometry jtsGeom = geom.toJTSGeometry();
350
                        if (indexInterval != -1)
351
                        {
352
                                for (int i=costs.length-1; i >= indexInterval; i--) {
353
                                        calculateConvexHull(jtsGeom, i);
354
                                }
355
                        }
356
                        double maxCost = costs[costs.length-1];
357
                        // Es -1 si caso l?mite externo
358
                        if (indexInterval < costs.length-1)
359
                        {
360
                                // Caso l?mite externo
361
                                if ((nodeEnd.getBestCost() > maxCost) &&                                                
362
                                                (nodeOrig.getBestCost() < maxCost))
363
                                {
364
                                        double pct = (maxCost - nodeOrig.getBestCost())/ edge.getWeight();
365
                                        LineString partial = NetworkUtils.getPartialLineString(jtsGeom, pct, edge.getDirec());
366
                                        calculateConvexHull(partial, costs.length-1);
367
                                        return;
368
                                }
369
                                // Parcial interno
370
                                maxCost = costs[indexInterval+1];
371
                                if ((nodeOrig.getBestCost() < maxCost) &&
372
                                                (nodeEnd.getBestCost() > maxCost)) 
373
                                {
374
                                        // A ese tramo hemos llegado parcialmente
375
                                         
376
                                        double pct = (maxCost - nodeOrig.getBestCost())/ edge.getWeight();
377
                                        try {
378
                                                LineString partial = NetworkUtils.getPartialLineString(jtsGeom, pct, edge.getDirec());
379
                                                calculateConvexHull(partial, indexInterval+1);                                                        
380
                                        }
381
                                        catch (Exception e)
382
                                        {
383
                                                e.printStackTrace();
384
                                        }
385
                                        
386
                                }
387
                        }
388
                } 
389

    
390
                
391
        }
392

    
393
        /**
394
         * @param jtsGeom
395
         * @param i
396
         */
397
        private void calculateConvexHull(Geometry jtsGeom, int i) {
398
                if (serviceAreaPolygons.size() <= i) { // se crea por primera vez
399
                        Geometry gIni = jtsGeom; 
400
                        serviceAreaPolygons.add(i, gIni);
401
                }
402
                else
403
                {
404
                        Geometry antG = serviceAreaPolygons.get(i);
405
                        if (antG == null)
406
                                antG = jtsGeom;
407
                        else
408
                        {
409
                                antG = antG.union(jtsGeom);                                
410
                        }
411
                        antG = antG.convexHull();
412
                        serviceAreaPolygons.set(i, antG);
413
                }
414
        }
415

    
416

    
417
        private void writePartialEdge(int i, IGeometry geom, GvEdge edge, GvNode nodeOrig, GvNode nodeEnd, int idFlag, double maxCost) throws BaseException {
418
                Geometry jtsGeom = geom.toJTSGeometry();
419
                double pct = (maxCost - nodeOrig.getBestCost())/ edge.getWeight();
420
                if (edge.getDirec() == 0) // Sentido inverso
421
                        pct = 1-pct;
422
                LineString partial = NetworkUtils.getPartialLineString(jtsGeom, pct, edge.getDirec());
423
                if (serviceArea == null)
424
                        serviceArea = partial;
425
                else
426
                {
427
                        serviceArea = serviceArea.union(partial);
428
                        serviceArea = serviceArea.convexHull();
429
                }
430
                
431
                IGeometry newGeom = FConverter.jts_to_igeometry(partial);
432

    
433
                Value[] values = new Value[7];
434
                values[0] = ValueFactory.createValue(i);
435
                values[1] = ValueFactory.createValue(edge.getIdEdge());
436
                values[2] = ValueFactory.createValue(nodeOrig.getBestCost());
437
                values[3] = ValueFactory.createValue(nodeOrig.getAccumulatedLength());
438
                values[4] = ValueFactory.createValue(maxCost);
439
                values[5] = ValueFactory.createValue(nodeOrig.getAccumulatedLength() + edge.getDistance()*pct);
440
                values[6] = ValueFactory.createValue(idFlag);
441
                DefaultFeature feat = new DefaultFeature(newGeom, values);
442
                IRowEdited row = new DefaultRowEdited(feat, DefaultRowEdited.STATUS_ADDED, i);
443
                shpWriter.process(row);
444
                
445
//                // TODO: TROZO DEL RESTO
446
//                int direc = 0;
447
//                pct = pct+0.02;
448
//                if (edge.getDirec() == 0)
449
//                {
450
//                        direc = 1;
451
//                        pct = pct - 0.04;
452
//                }
453
//                LineString partial2 = NetworkUtils.getPartialLineString(jtsGeom, pct, direc);                
454
//                IGeometry newGeom2 = FConverter.jts_to_igeometry(partial2);
455
//                values[6] = ValueFactory.createValue(-2);
456
//                DefaultFeature feat2 = new DefaultFeature(newGeom2, values);
457
//                IRowEdited row2 = new DefaultRowEdited(feat2, DefaultRowEdited.STATUS_ADDED, i);
458
//                shpWriter.process(row2);
459

    
460
                borderCoords.add(partial.getCoordinateN(partial.getNumPoints()-1)); 
461
                
462
                if (bDoCompactArea) {
463
//                        processCompact(partial);
464
                        Coordinate cLimit = null;
465
                        if (edge.getDirec() == 0) // Sentido inverso
466
                                cLimit = partial.getCoordinateN(0);
467
                        else
468
                                cLimit = partial.getCoordinateN(partial.getNumPoints()-1);
469
                        processCompact(cLimit.x, cLimit.y);
470
//                        processCompact(nodeEnd.getX(), nodeEnd.getY());
471
                }
472
                
473
        }
474
        
475
        public FLyrVect getBorderPoints() throws Exception {
476
                Value[] values = new Value[1];
477
                values[0] = ValueFactory.createValue(costs[costs.length-1]);
478

    
479
                File fTempPoints = new File(tempDirectoryPath + "/borderPoints.shp");
480
                
481
                FieldDescription[] fieldsPoints = new FieldDescription[1];
482
                FieldDescription fieldDesc = new FieldDescription();
483
                fieldDesc.setFieldName("COST");
484
                fieldDesc.setFieldType(Types.DOUBLE);
485
                fieldDesc.setFieldLength(20);
486
                fieldDesc.setFieldDecimalCount(5);
487
                fieldsPoints[0] = fieldDesc;
488

    
489
                SHPLayerDefinition layerDef = new SHPLayerDefinition();
490
                layerDef.setFile(fTempPoints);
491
                layerDef.setName("BorderPoints");                
492
                layerDef.setFieldsDesc(fieldsPoints);
493
                layerDef.setShapeType(FShape.POINT);
494

    
495
                
496
                ShpWriter shpWriter = new ShpWriter();
497
                shpWriter.setFile(fTempPoints);
498
                shpWriter.initialize(layerDef);
499

    
500
                int i=0;
501
                for (Iterator it = borderCoords.iterator(); it.hasNext();) {
502
                        Coordinate c = (Coordinate) it.next();
503
                        IGeometry geom = ShapeFactory.createPoint2D(c.x, c.y);
504
                        DefaultFeature feat = new DefaultFeature(geom, values);
505
                        IRowEdited row = new DefaultRowEdited(feat,
506
                                        DefaultRowEdited.STATUS_ADDED, i++);
507
                        shpWriter.process(row);
508
                        
509
                }
510
                shpWriter.postProcess();
511
                
512
                FLyrVect lyr = (FLyrVect) LayerFactory.createLayer(layerDef.getName(), "gvSIG shp driver", 
513
                                layerDef.getFile(), null);
514
                return lyr;
515

    
516
                
517
        }
518

    
519
        private void processCompact(LineString partial) {
520
                Coordinate cIni = partial.getCoordinateN(0);
521
                Coordinate cEnd = partial.getCoordinateN(partial.getNumPoints()-1);
522
//                System.out.println("PARTIAL c1=" + cIni + " cEnd=" + cEnd);
523
                processCompact(cIni.x, cIni.y);
524
                processCompact(cEnd.x, cEnd.y);
525
        }
526

    
527
        private void writeTotalEdge(int i, IGeometry geom, GvEdge edge,
528
                        GvNode nodeOrig, GvNode nodeEnd, int idFlag)
529
                        throws Exception {
530
                Value[] values = new Value[7];
531
                values[0] = ValueFactory.createValue(i);
532
                values[1] = ValueFactory.createValue(edge.getIdEdge());
533
                values[2] = ValueFactory.createValue(nodeOrig.getBestCost());
534
                values[3] = ValueFactory.createValue(nodeOrig.getAccumulatedLength());
535
                values[4] = ValueFactory.createValue(nodeEnd.getBestCost());
536
                values[5] = ValueFactory.createValue(nodeEnd.getAccumulatedLength());
537
                values[6] = ValueFactory.createValue(idFlag);
538
                
539
                if (bDoCompactArea) {
540
//                        System.out.println(" c1=" + cIni + " cEnd=" + cEnd);
541
//                        processCompact(nodeOrig.getX(), nodeOrig.getY());
542
//                        processCompact(nodeEnd.getX(), nodeEnd.getY());
543
                }
544

    
545

    
546
                DefaultFeature feat = new DefaultFeature(geom, values);
547
                IRowEdited row = new DefaultRowEdited(feat,
548
                                DefaultRowEdited.STATUS_ADDED, i);
549
                shpWriter.process(row);
550
        }
551

    
552
        private void processCompact(double x, double y) {
553
//                FPoint2D p = new FPoint2D(x,y);
554
                Coordinate c = new Coordinate(x,y);
555
//                System.out.println("PARTIAL c1=" + cIni + " cEnd=" + cEnd);
556
                if (!nodes.contains(c))
557
                        nodes.add(c);
558
                else
559
                {
560
                        System.out.print("Nodo ya contenido");
561
                }
562
                
563
        }
564

    
565
        public boolean adjacentEdgeVisited(GvNode fromNode, GvEdge edge) {
566
                insertVisitedEdge(edge);
567
                
568
                return false;
569
        }
570

    
571
        /**
572
         * Si el coste m?nimo del edge > costemax, salimos del m?todo.
573
         * Miramos si edge est? ya en la lista.
574
         * Si no est?, lo a?adimos.
575
         * Si est?, hay que mirar el porcentaje recorrido sobre ese tramo.
576
         * Casos posibles:
577
         * EdgeA al 100 % => No se a?ade este.
578
         * EdgeA.percentCost < 1.0. 
579
         *                 Comprobamos el percent de el nuevo. Si entre los dos suman > 1.0
580
         *                 marcamos el antiguo al 1.0 para que se escriba el tramo completo.
581
         * 
582
         *                 Si no suman 1.0, hay que a?adir este nuevo Edge, con el porcentaje
583
         *                 correspondiente.
584
         * @param edge
585
         */
586
        private void insertVisitedEdge(GvEdge edge) {
587
                IGraph g = net.getGraph();
588
                GvNode n1 = g.getNodeByID(edge.getIdNodeOrig());
589
                double maxCost = costs[costs .length-1];
590
                if (n1.getBestCost() > maxCost)
591
                        return; // edge outside service area.
592
                
593
                String key = "" + edge.getIdArc();
594
                if (!visitedEdges.containsKey(key))        
595
                {
596
                        visitedEdges.put(key, new VisitedEdge(edge));
597
//                        System.out.println("idEdge adjacent= " + edge.getIdEdge());
598
                }
599
                else
600
                {
601
                        VisitedEdge edgeAnt = visitedEdges.get(key);
602
//                        GvEdge savedEdge = edgeAnt.getEdge();
603
                        if (edgeAnt.getPercentcost() == 1.0)
604
                                return; // Ya est? completo, no a?adimos nada.
605
                        
606
                        double percentCostCalculated = (maxCost - n1.getBestCost())/ edge.getWeight();
607
                        if ((percentCostCalculated + edgeAnt.getPercentcost()) >= 1.0)
608
                                edgeAnt.setPercentCost(1.0);
609
                        else
610
                        {
611
                                visitedEdges.put(key + "_", new VisitedEdge(edge));
612
                        }
613

    
614
                }
615
        }
616

    
617
        public boolean minimumCostNodeSelected(GvNode node) {
618
//                IGraph g = net.getGraph();
619
//                int idEdge = node.getFromLink();
620
//                if (idEdge == -1) 
621
//                        return false;
622
//                GvEdge edge = g.getEdgeByID(idEdge);
623
//                insertVisitedEdge(edge);
624
                return false; // true if we want to stop Dijkstra
625
        }
626

    
627
        public void setIdFlag(int idFlag) {
628
                this.idFlag = idFlag;
629
        }
630
        
631
        /**
632
         * Write edges and polygons associated with active flag and costs
633
         * @param costs
634
         * @throws BaseException
635
         */
636
        public void writeServiceArea() throws Exception {
637
                Set<Map.Entry<String, VisitedEdge>> keySet = visitedEdges.entrySet();
638
                
639
                GvEdge edge;
640
                IGraph g = net.getGraph();
641
//                Integer idEdge;
642
                double maxCost = costs[costs .length-1];
643
                serviceAreaPolygons = new ArrayList<Geometry>(costs.length);
644
                for (int i=0; i < costs.length-1; i++)
645
                        serviceAreaPolygons.add(null);
646
                
647
                for (Map.Entry<String, VisitedEdge> entry : keySet) {
648
//                        idEdge = entry.getKey();
649
                        VisitedEdge visitedEdge = entry.getValue(); 
650
                        edge = visitedEdge.getEdge();
651
                        GvNode nodeEnd = g.getNodeByID(edge.getIdNodeEnd());
652
                        GvNode nodeOrig = g.getNodeByID(edge.getIdNodeOrig());
653
                        IGeometry geom;
654
                        try {
655
                                geom = adapter.getShape(edge.getIdArc());
656
                                processEdgeForPolygon(edge, nodeOrig, nodeEnd, geom, costs);
657
                                double costAux = nodeOrig.getBestCost() + edge.getWeight();
658
//                                if (nodeEnd.getBestCost() > nodeOrig.getBestCost())
659
                                {
660
                                        // TODO: REVISAR EL CASO EN EL QUE HAS LLEGADO POR LOS
661
                                        // 2 LADOS PERO HAY UN TRAMO INALCANZABLE ENMEDIO
662
                                        if (visitedEdge.getPercentcost() == 1.0) {
663
                                                // A ese tramo hemos llegado por completo
664
                                                // Recuperamos su distancia y etiquetamos.
665
                                                writeTotalEdge(edge.getIdArc(), geom, edge, nodeOrig, nodeEnd, idFlag);        
666
                                        }
667
                                        else
668
                                        {
669
                                                if (nodeOrig.getBestCost() < maxCost) {
670
                                                        // A ese tramo hemos llegado parcialmente
671
                                                        // Recuperamos su distancia y etiquetamos.
672
                                                        writePartialEdge(edge.getIdArc(), geom, edge, nodeOrig, nodeEnd, idFlag, maxCost);        
673
                                                        
674
                                                }
675
                                        } // else
676
                                } // if nodeEnd > nodeOrig
677
                        
678
                        } catch (Exception e) {
679
                                e.printStackTrace();
680
                                throw new RuntimeException(e);
681
                        }
682
                        
683
                } // for
684
                for (int j=serviceAreaPolygons.size()-1; j>=0; j--) {
685
                        Geometry jtsGeom = serviceAreaPolygons.get(j);
686
                        writePolygon(idFlag, costs[j], jtsGeom);
687
                }
688

    
689
                if (bDoCompactArea) {
690
                        calculateTriangulation();
691
                }
692
                
693
        }
694

    
695
        private void calculateTriangulation() {
696
                
697
                // Centroide
698
                CentroidPoint centroid = new CentroidPoint();
699
                for (Iterator it = nodes.iterator(); it.hasNext();)
700
                {
701
                        Coordinate node = (Coordinate) it.next();
702
                        centroid.add(node);
703
                }
704
                nodes.add(centroid.getCentroid());
705
                
706
                int numPoints = nodes.size();
707
            double[][] samples = new double[2][numPoints];
708
            double[] samp0 = samples[0];
709
            double[] samp1 = samples[1];
710
            Iterator it = nodes.iterator();
711
            for (int i=0; i<numPoints; i++) {
712
                    Coordinate node = (Coordinate) it.next();
713
                    samp0[i] = node.x;
714
                    samp1[i] = node.y;
715
            }
716

    
717
            try {
718
                        tri2 = new DelaunayWatson(samples);
719
                        tri2.improve(samples, 10);
720
                        
721
                        System.out.println("Fin de trayecto. Num. tri?ngulos=" + tri2.Tri.length);
722
                        for (int i=0; i< tri2.Tri.length; i++) {
723
                              writeTri(tri2.Tri[i], samples);
724
                    }
725
                } catch (Exception e) {
726
                        // TODO Auto-generated catch block
727
                        e.printStackTrace();
728
                }
729

    
730
                
731
        }
732
        private void writeTri(int[] vertex, double[][] points) throws BaseException {
733
                Value[] values = new Value[2];
734
                values[0] = ValueFactory.createValue(2.0);
735
                values[1] = ValueFactory.createValue(1);
736
                
737
                Coordinate c1 = new Coordinate(points[0][vertex[0]], points[1][vertex[0]]);
738
                Coordinate c2 = new Coordinate(points[0][vertex[1]], points[1][vertex[1]]);
739
                Coordinate c3 = new Coordinate(points[0][vertex[2]], points[1][vertex[2]]);
740
                Coordinate[] c = new Coordinate[4];
741
                c[0] = c1;
742
                c[1] = c3;
743
                c[2] = c2;
744
                c[3] = c1;
745
                LinearRing linRing = null;
746
                if (CGAlgorithms.isCCW(c))
747
                {
748
                        Coordinate[] ccw = new Coordinate[4];
749
                        ccw[0] = c1;
750
                        ccw[1] = c2;
751
                        ccw[2] = c3;
752
                        ccw[3] = c1;
753
                        linRing = gf.createLinearRing(ccw);
754
                }
755
                else
756
                {
757
                        linRing = gf.createLinearRing(c);
758
//                        return;
759
                }
760
                 
761
                Polygon pol = gf.createPolygon(linRing, null);
762
                
763
                IGeometry geom = FConverter.jts_to_igeometry(pol);
764
                DefaultFeature feat = new DefaultFeature(geom, values);
765
                IRowEdited row = new DefaultRowEdited(feat, DefaultRowEdited.STATUS_ADDED, idFlag);
766
//                shpWriterPol.process(row);
767
                shpWriterTri.process(row);
768
                
769
        }
770

    
771
        private void writePolygon(int idFlag, double maxCost, Geometry jtsGeom) throws BaseException {
772
                Value[] values = new Value[2];
773
                values[0] = ValueFactory.createValue(maxCost);
774
                values[1] = ValueFactory.createValue(idFlag);
775
                
776
                IGeometry geom = FConverter.jts_to_igeometry(jtsGeom);
777
                DefaultFeature feat = new DefaultFeature(geom, values);
778
                IRowEdited row = new DefaultRowEdited(feat, DefaultRowEdited.STATUS_ADDED, idFlag);
779
                shpWriterPol.process(row);
780
        }
781

    
782
        /**
783
         * Close writers.
784
         * @throws Exception
785
         */
786
        public void closeFiles() throws Exception {
787
//                for (int j=serviceAreaPolygons.size()-1; j>=0; j--) {
788
//                        Geometry jtsGeom = serviceAreaPolygons.get(j);
789
//                        writePolygon(idFlag, costs[j], jtsGeom);
790
//                }
791

    
792
                shpWriter.postProcess();
793
                shpWriterPol.postProcess();
794
                shpWriterTri.postProcess();
795
                
796
                adapter.stop();
797
                
798
                
799

    
800
        }
801
        public double[] getCosts() {
802
                return costs;
803
        }
804

    
805
        public void setCosts(double[] costs) {
806
                this.costs = costs;
807
        }
808

    
809
        public FLyrVect getPolygonLayer() throws Exception {
810
                FLyrVect lyr = (FLyrVect) LayerFactory.createLayer(layerDefPol.getName(), "gvSIG shp driver", 
811
                                layerDefPol.getFile(), null);
812
                return lyr;
813
        }
814

    
815
        public FLyrVect getLineLayer() throws Exception {
816
                FLyrVect lyr = (FLyrVect) LayerFactory.createLayer(layerDef.getName(), "gvSIG shp driver", 
817
                                layerDef.getFile(), null);
818
                return lyr;
819
        }
820

    
821
        public boolean isDoCompactArea() {
822
                return bDoCompactArea;
823
        }
824

    
825
        public void setDoCompactArea(boolean doCompactArea) {
826
                bDoCompactArea = doCompactArea;
827
        }
828

    
829
}