Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extGraph / src / org / gvsig / graph / ClosestFacilityController.java @ 31984

History | View | Annotate | Download (32.3 KB)

1
package org.gvsig.graph;
2

    
3
import java.awt.Color;
4
import java.io.File;
5
import java.io.FileNotFoundException;
6
import java.sql.Types;
7
import java.util.ArrayList;
8
import java.util.BitSet;
9
import java.util.Hashtable;
10
import java.util.Iterator;
11
import java.util.List;
12
import java.util.logging.Logger;
13

    
14
import org.gvsig.graph.core.GraphException;
15
import org.gvsig.graph.core.GvFlag;
16
import org.gvsig.graph.core.IFlagListener;
17
import org.gvsig.graph.core.Network;
18
import org.gvsig.graph.core.NetworkUtils;
19
import org.gvsig.graph.gui.RouteControlPanel;
20
import org.gvsig.graph.gui.RouteReportPanel;
21
import org.gvsig.graph.solvers.OneToManySolver;
22
import org.gvsig.graph.solvers.Route;
23
import org.gvsig.graph.solvers.ShortestPathSolverAStar;
24
import org.gvsig.graph.tools.FlagListener;
25

    
26
import com.hardcode.driverManager.DriverLoadException;
27
import com.hardcode.gdbms.driver.exceptions.InitializeWriterException;
28
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
29
import com.hardcode.gdbms.engine.data.DataSourceFactory;
30
import com.hardcode.gdbms.engine.data.NoSuchTableException;
31
import com.hardcode.gdbms.engine.data.driver.ObjectDriver;
32
import com.hardcode.gdbms.engine.values.StringValue;
33
import com.hardcode.gdbms.engine.values.Value;
34
import com.hardcode.gdbms.engine.values.ValueFactory;
35
import com.iver.andami.PluginServices;
36
import com.iver.cit.gvsig.exceptions.visitors.ProcessWriterVisitorException;
37
import com.iver.cit.gvsig.exceptions.visitors.StartWriterVisitorException;
38
import com.iver.cit.gvsig.exceptions.visitors.StopWriterVisitorException;
39
import com.iver.cit.gvsig.fmap.MapControl;
40
import com.iver.cit.gvsig.fmap.core.DefaultFeature;
41
import com.iver.cit.gvsig.fmap.core.FPoint2D;
42
import com.iver.cit.gvsig.fmap.core.FShape;
43
import com.iver.cit.gvsig.fmap.core.IFeature;
44
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
45
import com.iver.cit.gvsig.fmap.drivers.ExternalData;
46
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
47
import com.iver.cit.gvsig.fmap.drivers.LayerDefinition;
48
import com.iver.cit.gvsig.fmap.drivers.shp.IndexedShpDriver;
49
import com.iver.cit.gvsig.fmap.edition.DefaultRowEdited;
50
import com.iver.cit.gvsig.fmap.edition.IRowEdited;
51
import com.iver.cit.gvsig.fmap.edition.writers.shp.ShpWriter;
52
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
53
import com.iver.cit.gvsig.fmap.layers.LayerFactory;
54
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
55
import com.iver.cit.gvsig.util.GvSession;
56
import com.vividsolutions.jts.geom.Coordinate;
57
import com.vividsolutions.jts.geom.Geometry;
58
import com.vividsolutions.jts.geom.MultiPoint;
59
import com.vividsolutions.jts.geom.Point;
60

    
61
/**
62
 * @author falario
63
 *
64
 */
65

    
66
public class ClosestFacilityController implements IFlagListener{
67
        
68
        //private ClosestFacilityDialog cfd;
69
        private Network network;
70
        private MapControl mpCtrl;
71
        
72
        //private Hashtable facilitiesLayers;
73
        //private Hashtable events;
74
        private GvFlag sourceEvent;
75
        private Hashtable facilities;
76
        private int toolMaxFacilitiesNumber;
77
        private int maxFacilitiesNumber;
78
        private double facilitiesMaxLimit;
79
        private boolean toEvent;
80
        private ArrayList solvedFacilities;
81
        private Hashtable solvedRoutes;
82
        
83
        private static final int EVENT_ADDED = 0;
84
        private static final int EVENT_REMOVED = 1;
85
        private static final int EVENTS_REMOVED = 2;
86
        private static final int EVENT_MODIFIED = 3;
87
        
88
        private static final int FACILITY_ADDED = 4;
89
        private static final int FACILITY_REMOVED = 5;
90
        private static final int FACILITIES_REMOVED = 6;
91
        private static final int FACILITY_MODIFIED = 7;
92
        
93
        private static final int SOLVEDFACILITY_ADDED = 8;
94
        private static final int SOLVEDFACILITIES_REMOVED = 9;
95
        
96
        private ArrayList closestFacilitiesListeners;
97
        private FLyrVect layerFacilities;
98
        private boolean onlySelectedFacilities;
99
        private GvFlag[] events;
100
        
101
        private boolean solutionFromEventSelected;
102
        private GvFlag solutionEventSelected;
103
        
104
        private PluginServices ps=PluginServices.getPluginServices(this);
105
        
106
        private static final Logger logger = Logger.getLogger(ClosestFacilityController.class.getName());
107
        
108
        public ClosestFacilityController(Network network, MapControl mpCtrl){
109
                this.network=network;
110
                this.network.addFlagListener(this);
111
                this.mpCtrl=mpCtrl;
112
                
113
                //this.facilitiesLayers=new Hashtable();
114
                this.facilities=new Hashtable();
115
                this.maxFacilitiesNumber=0;
116
                this.toolMaxFacilitiesNumber=15;
117
                this.toEvent=true;
118
                this.solvedFacilities=new ArrayList(this.toolMaxFacilitiesNumber);
119
                this.solvedRoutes=new Hashtable();                
120
                this.closestFacilitiesListeners=new ArrayList();
121
                this.layerFacilities=null;
122
        }
123
        
124
        /**
125
         * Adds a ClosestFacilityListener to the ClosestFacilityController
126
         * @param listener the ClosestFacilityListener to be added
127
         */
128
        public void addClosestFacilityListener(IClosestFacilityListener listener){
129
                this.closestFacilitiesListeners.add(listener);
130
                logger.info("Listener: "+listener+" a?adido");
131
        }
132
        
133
        /**
134
         * Removes an ClosestFacilityListener from the ClosestFacilityController
135
         * @param listener the ClosestFacilityListener to be removed
136
         */
137
        public void removeClosestFacilityListener(IClosestFacilityListener listener){
138
                this.closestFacilitiesListeners.remove(listener);
139
                logger.info("Listener: "+listener+" borrado");
140
        }
141
        
142
        private void informListeners(int reason, GvFlag flag1, GvFlag flag2) {
143
                Iterator it=this.closestFacilitiesListeners.iterator();
144
                        switch(reason){
145
                                case EVENT_ADDED:
146
                                        logger.info("Evento "+flag1+" a?adido");
147
                                        while(it.hasNext()){
148
                                                ((IClosestFacilityListener)it.next()).eventAdded(flag1);
149
                                        }
150
                                        break;
151
                                
152
                                case EVENT_REMOVED:
153
                                        logger.info("Evento "+flag1+" borrado");
154
                                        while(it.hasNext()){
155
                                                ((IClosestFacilityListener)it.next()).eventRemoved(flag1);
156
                                        }
157
                                        break;
158
                                case EVENTS_REMOVED:
159
                                        logger.info("Borrados todos los eventos");
160
                                        while(it.hasNext()){
161
                                                ((IClosestFacilityListener)it.next()).allEventsRemoved();
162
                                        }
163
                                        break;
164
                                case EVENT_MODIFIED:
165
                                        logger.info("Modificaci?n del evento "+flag1+" pasa a ser: "+flag2);
166
                                        while(it.hasNext()){
167
                                                ((IClosestFacilityListener)it.next()).eventModified(flag1, flag2);
168
                                        }
169
                                        break;
170
                                case FACILITY_ADDED:
171
                                        logger.info("Proveedor a?adido: "+flag1);
172
                                        while(it.hasNext()){
173
                                                ((IClosestFacilityListener)it.next()).facilityAdded(flag1);
174
                                        }
175
                                        break;
176
                                case FACILITY_REMOVED:
177
                                        logger.info("Proveedor borrado: "+flag1);
178
                                        while(it.hasNext()){
179
                                                ((IClosestFacilityListener)it.next()).facilityRemoved(flag1);
180
                                        }
181
                                        break;
182
                                case FACILITIES_REMOVED:
183
                                        logger.info("Todos los proveedores han sido borrados");
184
                                        while(it.hasNext()){
185
                                                ((IClosestFacilityListener)it.next()).allFacilitiesRemoved();
186
                                        }
187
                                        break;
188
                                case FACILITY_MODIFIED:
189
                                        logger.info("Modificaci?n del proveedor "+flag1+" pasa a ser: "+flag2);
190
                                        while(it.hasNext()){
191
                                                ((IClosestFacilityListener)it.next()).facilityModified(flag1, flag2);
192
                                        }
193
                                        break;
194
                                case SOLVEDFACILITY_ADDED:
195
                                        logger.info("A?adido un proveedor a la soluci?n: "+flag1);
196
                                        while(it.hasNext()){
197
                                                ((IClosestFacilityListener)it.next()).addedSolvedFacility(flag1);
198
                                        }
199
                                        break;
200
                                case SOLVEDFACILITIES_REMOVED:
201
                                        logger.info("Los proveedores de la soluci?n han sido eliminados");
202
                                        while(it.hasNext()){
203
                                                ((IClosestFacilityListener)it.next()).removedSolvedFacilities();
204
                                        }
205
                                        break;
206
                        }
207
        }
208
        
209
        /**
210
         * Returns the network used in the ClosestFacilityController
211
         * @return the network used in the ClosestFacilityController
212
         */
213
        public Network getNetwork(){
214
                return this.network;
215
        }
216
        
217
        /**
218
         * Sets the network to be used in the ClosestFacilityController
219
         * @param network The networ wich will be used in the ClosestFacilityController
220
         */
221
        public void setNetwork(Network network){
222
                this.network=network;
223
        }
224
        
225
        /**
226
         * The maximum number of facilities to be considered in the solution
227
         * @param maxFacilitiesNumber sets the maximum number of facilities that will be considered in the solution
228
         */
229
        public void setMaxFacilitiesNumber(int maxFacilitiesNumber){
230
                this.maxFacilitiesNumber = (maxFacilitiesNumber<=this.toolMaxFacilitiesNumber)? maxFacilitiesNumber : this.toolMaxFacilitiesNumber;
231
                //this.cfd.setMaxFacilitiesNumber(maxFacilitiesNumber);
232
        }
233
        
234
        /**
235
         * Gets the maximum number of facilities to be considered in the solution
236
         * @return the maximum number of facilities to be considered in the solution
237
         */
238
        public int getMaxFacilitiesNumber(){
239
                return this.maxFacilitiesNumber;
240
        }
241
        
242
        /**
243
         * Set the default maximum number of facilities to be considered in the solution
244
         * @param toolMaxFacilitiesNumber the default maximum number of facilities to be considered in the solution
245
         */
246
        public void setToolMaxFacilitiesNumber(int toolMaxFacilitiesNumber){
247
                this.toolMaxFacilitiesNumber=toolMaxFacilitiesNumber;
248
        }
249
        
250
        /**
251
         * Gets the default maximum number of facilities to be considered in the solution
252
         * @return the default maximum number of facilities to be considered in the solution
253
         */
254
        public int getToolMaxFacilitiesNumber(){
255
                return this.toolMaxFacilitiesNumber;
256
        }
257
        
258
        /**
259
         * ?It won't be considered in the solution facilities that have a much higher cost than this property
260
         * @return the maximum cost
261
         */
262
        public double getFacilitiesMaxLimit(){
263
                return this.facilitiesMaxLimit;
264
        }
265
        
266
        /**
267
         * It won't be considered in the solution facilities that have a much higher cost than this property
268
         * @param facilitiesMaxLimit the maximum cost 
269
         */
270
        public void setFacilitiesMaxLimit(double facilitiesMaxLimit){
271
                this.facilitiesMaxLimit=facilitiesMaxLimit;
272
        }
273
        
274
        /**
275
         * Set the direction of the route from the facility to the event
276
         */
277
        public void setToEvent(){
278
                this.toEvent=true;
279
        }
280
        
281
        /**
282
         * Set the direction of the route from the event to the facility
283
         */
284
        public void setFromEvent(){
285
                this.toEvent=false;
286
        }
287
        
288
        /**
289
         * Determines if the direction of the route is from the facility to the event
290
         * @return true if the direction of the route is from the facility to the event, false otherwise
291
         */
292
        public boolean isToEvent(){
293
                return this.toEvent;
294
        }
295
        
296
        /**
297
         * Determines if the direction of the route is from the event to the facility
298
         * @return true if the direction of the route is from the event to the facility, false otherwise
299
         */
300
        public boolean isFromEvent(){
301
                return !this.toEvent;
302
        }
303
        
304
        /**
305
         * Center the graphics used in the ClosestFacilityController on the flag
306
         * @param flag the graphics will be centered on this flag
307
         */
308
        public void centerGraphicsOnFlag(GvFlag flag) {
309
                NetworkUtils.centerGraphicsOnFlag(this.mpCtrl, flag);        
310
        }
311
        
312
        /**
313
         * The graphics used in the ClosestFacilityController will be centered on the minimum rectangle that contains all the flags
314
         * @param flags the array of flags
315
         */
316
        public void centerGraphicsOnFlags(GvFlag[] flags){
317
                NetworkUtils.centerGraphicsOnFlags(this.mpCtrl, flags);
318
        }
319
        
320
        /**
321
         * Adds an event to the network used in the ClosestFacilityController
322
         * @param event the event to be added
323
         */
324
        private void addEvent(GvFlag event){
325
                this.network.addFlag(event);
326
                //NetworkUtils.addGraphicFlag(this.mpCtrl, event);
327
                //this.mpCtrl.drawGraphics();
328
                this.informListeners(EVENT_ADDED, event, null);
329
        }
330
        
331
        /**
332
         * Shows the position of the flag on the graphics
333
         * @param event the event to be shown
334
         */
335
        public void addEventToGraphics(GvFlag event) {
336
                NetworkUtils.addGraphicFlag(this.mpCtrl, event);
337
                this.mpCtrl.drawGraphics();
338
        }
339
        
340
        /**
341
         * Sets the event used to find the closest facility
342
         * @param event the event used to find the closest facility
343
         */
344
        public void setSourceEvent(GvFlag event){
345
                this.sourceEvent=event;
346
        }
347
        
348
        /**
349
         * Gets the event used to find the closest facility
350
         * @return the event used to find the closest facility
351
         */
352
        public GvFlag getSourceEvent(){
353
                return this.sourceEvent;
354
        }
355
        
356
        private GvFlag createFlagFromGeometry(Geometry geom, double tol) throws GraphException{
357
                GvFlag flag=null;
358
                if (geom instanceof Point || geom instanceof MultiPoint){
359
                        Coordinate[] coords = geom.getCoordinates();
360
                        for (int j = 0; j < coords.length; j++) {
361
                                flag = this.network.createFlag(coords[j].x, coords[j].y, tol);
362
                                if (flag == null)
363
                                {
364
                                        // segundo intento:
365
                                        flag = this.network.createFlag(coords[j].x, coords[j].y, 4*tol);
366
                                }
367

    
368
                        }
369
                }
370
                
371
                return flag;
372
        }
373

    
374
        public boolean getOnlySelectedFacilities(){
375
                return this.onlySelectedFacilities;
376
        }
377

    
378
        public void setOnlySelectedFacilities(boolean onlySelectedFacilities) {
379
                this.onlySelectedFacilities=onlySelectedFacilities;
380
        }
381
        
382
        public void setLayerFacilities(FLyrVect layerFacilities) {
383
                this.layerFacilities=layerFacilities;
384
        }
385
        
386
        public int loadFacilitiesFromLayer(FLyrVect layerFacilities, boolean onlySelectedFacilities) throws ReadDriverException, GraphException{
387
                long init=System.currentTimeMillis();
388
                GvFlag flag=null;
389
                int rejectedFacilities=0;
390
                int incrementIdFlag=0;
391
                int fieldDescriptionIndex=-1;
392
                this.removeAllFacilities();
393
                if(this.getSourceEvent()!=null){
394
                        incrementIdFlag=this.getSourceEvent().getIdFlag()+1;
395
                }
396
                double realTol = this.mpCtrl.getViewPort().toMapDistance(FlagListener.pixelTolerance);
397
                SelectableDataSource ds=layerFacilities.getRecordset();
398
                FieldDescription[] fieldDesc=ds.getFieldsDescription();
399
                if(fieldDesc!=null){
400
                        for (int i = 0; i < fieldDesc.length && fieldDescriptionIndex == -1; i++) {
401
                                if(fieldDesc[i].getFieldName().equalsIgnoreCase("descript") && fieldDesc[i].getFieldType()==Types.VARCHAR){
402
                                        fieldDescriptionIndex=i;
403
                                }
404
                        }
405
                }
406
                if(onlySelectedFacilities){
407
                        BitSet selection=layerFacilities.getRecordset().getSelection();
408
                        for(int i=selection.nextSetBit(0), j=0; i>=0; i=selection.nextSetBit(i+1), j++) {
409
                                flag=this.createFlagFromGeometry(layerFacilities.getSource().getShape(i).toJTSGeometry(), realTol);
410
                                if(flag==null) rejectedFacilities++;
411
                                else{
412
                                        if(fieldDescriptionIndex>=0 && fieldDescriptionIndex<fieldDesc.length){
413
                                                Value[] values=ds.getRow(i);
414
                                                if(values[fieldDescriptionIndex] instanceof StringValue){
415
                                                        flag.setDescription(((StringValue)values[fieldDescriptionIndex]).toString());
416
                                                }
417
                                        }
418
                                        else{
419
                                                flag.setDescription(ps.getText("facility")+" "+j);
420
                                        }
421
                                        flag.setIdFlag(i+incrementIdFlag);
422
                                        this.addFacility(flag);
423
                                }
424
                        }
425
                }
426
                else{
427
                        int shapesCount=layerFacilities.getSource().getShapeCount();
428
                        for (int i = 0; i < shapesCount; i++) {
429
                                flag=this.createFlagFromGeometry(layerFacilities.getSource().getShape(i).toJTSGeometry(), realTol);
430
                                if(flag==null) rejectedFacilities++;
431
                                else{
432
                                        if(fieldDescriptionIndex>=0 && fieldDescriptionIndex<fieldDesc.length){
433
                                                Value[] values=ds.getRow(i);
434
                                                if(values[fieldDescriptionIndex] instanceof StringValue){
435
                                                        flag.setDescription(((StringValue)values[fieldDescriptionIndex]).toString());
436
                                                }
437
                                        }
438
                                        else{
439
                                                flag.setDescription(ps.getText("facility")+" "+i);
440
                                        }
441
                                        flag.setIdFlag(i+incrementIdFlag);
442
                                        this.addFacility(flag);
443
                                }
444
                        }
445
                }
446
                
447
                logger.info(ps.getText("facilities_loaded_in")+" "+(System.currentTimeMillis()-init)+" millis");
448
                return rejectedFacilities;
449
        }
450
        
451
        private SelectableDataSource getRecordset(IndexedShpDriver shpDriver) throws DriverLoadException, ReadDriverException, NoSuchTableException{
452
                SelectableDataSource ds;
453
                //VectorialFileDriver driver = (VectorialFileDriver) getDriver();
454

    
455
                if (shpDriver instanceof ExternalData) {
456
                        ExternalData ed = (ExternalData) shpDriver;
457
                        File dataFile = ed.getDataFile(shpDriver.getFile());
458
                        String driverName = ed.getDataDriverName();
459

    
460
                        String name = LayerFactory.getDataSourceFactory().addFileDataSource(driverName,
461
                                        dataFile.getAbsolutePath());
462
                        //                                         CHEMA: AUTOMATIC DATA SOURCE
463
                        //ds = new SelectableDataSource(LayerFactory.getDataSourceFactory().createRandomDataSource(name, DataSourceFactory.MANUAL_OPENING));
464
                        ds = new SelectableDataSource(LayerFactory.getDataSourceFactory().createRandomDataSource(name, DataSourceFactory.AUTOMATIC_OPENING));
465
                } else if (shpDriver instanceof ObjectDriver) {
466
                        String name = LayerFactory.getDataSourceFactory().addDataSource((ObjectDriver)shpDriver);
467
                        //                                         CHEMA: AUTOMATIC DATA SOURCE
468
                        //ds = new SelectableDataSource(LayerFactory.getDataSourceFactory().createRandomDataSource(name, DataSourceFactory.MANUAL_OPENING));
469
                        ds = new SelectableDataSource(LayerFactory.getDataSourceFactory().createRandomDataSource(name, DataSourceFactory.AUTOMATIC_OPENING));
470
                } else {
471
                        return null;
472
                }
473
                return ds;
474
        }
475

    
476
        public void loadEventsFromFile(File file) throws FileNotFoundException, NullPointerException, GraphException, ReadDriverException, DriverLoadException, NoSuchTableException, Exception{
477
//                Cargar el fichero seleccionado, comprobando que sea de puntos
478
                IndexedShpDriver shpDriver=null;
479
                SelectableDataSource ds=null;
480
                FieldDescription[] fieldDesc=null;
481
                int fieldDescriptionIndex=-1;
482

    
483
                if(!file.exists()){
484
                        throw new FileNotFoundException(ps.getText("the_file")+" "+file.getName()+" "+ps.getText("doesnt_exist"));
485
                }
486
                shpDriver=new IndexedShpDriver();
487
                shpDriver.open(file);
488
                shpDriver.initialize();
489
                if(shpDriver.getShapeType()==FShape.POINT){
490
                        ds=this.getRecordset(shpDriver);
491
                        fieldDesc=ds.getFieldsDescription();
492
                        if(fieldDesc!=null){
493
                                for (int i = 0; i < fieldDesc.length && fieldDescriptionIndex == -1; i++) {
494
                                        if(fieldDesc[i].getFieldName().equalsIgnoreCase("descript") && fieldDesc[i].getFieldType()==Types.VARCHAR){
495
                                                fieldDescriptionIndex=i;
496
                                        }
497
                                }
498
                        }
499

    
500
                        int shapeCount=shpDriver.getShapeCount();
501
                        double realTol = this.mpCtrl.getViewPort().toMapDistance(FlagListener.pixelTolerance);
502
                        GvFlag flag;
503
                        for (int i = 0; i < shapeCount; i++) {
504
                                /*FPoint2D point=(FPoint2D)shpDriver.getShape(i).getInternalShape();
505
                                        flag=this.network.createFlag(point.getX(), point.getY(), 10);
506
                                        this.network.addFlag(flag);
507
                                        //this.addEvent(flag);*/
508

    
509
                                Geometry geo = shpDriver.getShape(i).toJTSGeometry();
510
                                if (!((geo instanceof Point) || (geo instanceof MultiPoint)))
511
                                        continue;
512

    
513
                                Coordinate[] coords = geo.getCoordinates();
514
                                for (int j = 0; j < coords.length; j++) {
515
                                        flag = this.network.createFlag(coords[j].x, coords[j].y, realTol);
516
                                        if (flag == null)
517
                                        {
518
                                                // segundo intento:
519
                                                flag = this.network.createFlag(coords[j].x, coords[j].y, 4*realTol);
520
                                                if (flag == null)
521
                                                {                                                                
522
                                                        throw new NullPointerException(ps.getText("event")+" " + i + " "+ps.getText("out_of_the_network")+"."+" "+ps.getText("tolerance")+"=" + realTol);
523
                                                        //NotificationManager.addError("No se puedo situar el registro " + i +"Por favor, compruebe que est? encima de la red o aumente la toleracina.", e);
524
                                                }
525
                                        }
526
                                        if (flag != null)
527
                                        {
528
                                                if(fieldDescriptionIndex>=0 && fieldDescriptionIndex<fieldDesc.length){
529
                                                        Value[] values=ds.getRow(i);
530
                                                        if(values[fieldDescriptionIndex] instanceof StringValue){
531
                                                                flag.setDescription(((StringValue)values[fieldDescriptionIndex]).toString());
532
                                                        }
533
                                                }
534
                                                this.addEvent(flag);
535
                                        }
536

    
537
                                } // for j
538
                        } // for i
539
                        shpDriver.close();
540
                }
541
                else{
542
                        shpDriver.close();
543
                        throw new Exception(ps.getText("only_points_in_file"));
544
                }
545
        }
546
        
547
        public void createSHPEvents(File file) throws InitializeWriterException, StartWriterVisitorException, StopWriterVisitorException, ProcessWriterVisitorException {
548
                LayerDefinition tDef = new LayerDefinition();
549
                tDef.setShapeType(FShape.POINT);
550
                FieldDescription[] fieldDescriptions=new FieldDescription[2];
551
                fieldDescriptions[0]=new FieldDescription();
552
                fieldDescriptions[0].setFieldName("IdFlag");
553
                fieldDescriptions[0].setFieldType(Types.INTEGER);
554
                fieldDescriptions[1]=new FieldDescription();
555
                fieldDescriptions[1].setFieldName("Descript");
556
                fieldDescriptions[1].setFieldType(Types.VARCHAR);
557
                fieldDescriptions[1].setFieldLength(50);
558
                
559
                tDef.setFieldsDesc(fieldDescriptions);
560
                 
561
                ShpWriter shpDrv = new ShpWriter();
562
                shpDrv.setFile(file);
563
                shpDrv.initialize(tDef);
564
                 
565
                shpDrv.preProcess();
566
                int rowIndex = 0;
567
                GvFlag[] events=this.network.getFlags();
568
                for (int i = 0; i < events.length; i++) {
569
                        Value[] rowValues = new Value[]{ValueFactory.createValue(events[i].getIdFlag()), ValueFactory.createValue(events[i].getDescription())};
570
                        IFeature feat = new DefaultFeature(ShapeFactory.createPoint2D(new FPoint2D(events[i].getOriginalPoint())), rowValues, "" + rowIndex);
571
                        DefaultRowEdited row = new DefaultRowEdited(feat, IRowEdited.STATUS_ADDED, rowIndex);
572
                        row.setAttributes(rowValues);
573
                        shpDrv.process(row);
574
                }
575
                  
576
                shpDrv.postProcess();
577
        }
578
        
579
        public GvFlag getEvent(int idEvent){
580
                GvFlag[] flags=this.network.getFlags();
581
                GvFlag flag=null;
582
                
583
                for (int i = 0; i < flags.length && flag==null; i++) {
584
                        if(flags[i].getIdFlag()==idEvent) flag=flags[i];
585
                }
586
                
587
                return flag;
588
        }
589
        
590

    
591
        public GvFlag getEventByIndex(int index) {
592
                try{
593
                        return this.network.getFlags()[index];
594
                }
595
                catch(IndexOutOfBoundsException except){
596
                        return null;
597
                }
598
        }
599
        
600
        public int getEventCount(){
601
                return this.network.getFlags().length;
602
        }
603
        
604
        public void removeEvent(GvFlag event){
605
                this.network.removeFlag(event);
606
                NetworkUtils.clearFlagFromGraphics(this.mpCtrl, event);
607
                //this.mpCtrl.drawGraphics();
608
                this.informListeners(EVENT_REMOVED, event, null);
609
        }
610
        
611
        public void removeEventFromGraphics(GvFlag event){
612
                NetworkUtils.clearFlagFromGraphics(this.mpCtrl, event);
613
                this.mpCtrl.drawGraphics();
614
        }
615
        
616
        public void removeAllEvents(){
617
                this.network.removeFlags();
618
                this.informListeners(EVENTS_REMOVED, null, null);
619
        }
620
        
621
        public void flashFacilitiesOnGraphics() throws ReadDriverException {
622
                Iterator it=this.facilities.values().iterator();
623
                
624
                this.mpCtrl.repaint();
625
                while(it.hasNext()){
626
                        this.flashFlag((GvFlag)it.next(), Color.BLUE, 5);
627
                }
628
        }
629
        
630
        @SuppressWarnings("unchecked")
631
        public void addFacility(GvFlag facility){
632
                if(this.facilities.get(facility.getIdFlag())==null){
633
                        this.facilities.put(String.valueOf(facility.getIdFlag()), facility);
634
                        this.informListeners(FACILITY_ADDED, facility, null);
635
                }
636
        }
637
        
638
        /**
639
         * @param idFacility the id of the facility to be returned
640
         * @return the facility that correspond with the specified id
641
         */
642
        public GvFlag getFacility(int idFacility){
643
                return (GvFlag)this.facilities.get(String.valueOf(idFacility));
644
        }
645
        
646
        /**
647
         * The ammount number of facilities
648
         * @return the number of facilities
649
         */
650
        public int getFacilitiesCount(){
651
                return this.facilities.size();
652
        }
653
        
654
        /**
655
         * Removes the facilities with the specified Id
656
         * @param idFacility the id of the facility to be removed
657
         */
658
        public void removeFacility(int idFacility){
659
                GvFlag flag=null;
660
                if((flag=this.getFacility(idFacility))!=null){
661
                        this.facilities.remove(idFacility);
662
                        this.informListeners(FACILITY_REMOVED, flag, null);
663
                }
664
        }
665
        
666
        /**
667
         * Removes all the facilities
668
         */
669
        public void removeAllFacilities(){
670
                this.facilities=new Hashtable();
671
                this.informListeners(FACILITIES_REMOVED, null, null);
672
        }
673
        
674
        /*public GvFlag getSelectedEvent(){
675
                 return this.cfd.getSelectedEvent();
676
        }*/
677
        
678
        private void addSortedSolvedFacility(GvFlag flag){
679
                boolean added=false;
680
                int index=0;
681
                double flagCost=flag.getCost();
682
                if(flagCost<=this.facilitiesMaxLimit && flagCost>=0 && this.solvedFacilities.size()<this.maxFacilitiesNumber){
683
                        for (index = 0; !added  && index < this.solvedFacilities.size(); index++) {
684
                                if(flagCost<=((GvFlag)this.solvedFacilities.get(index)).getCost()){
685
                                        this.addSolvedFacility(index, flag);
686
                                        added=true;
687
                                }
688
                        }
689
                
690
                        if(!added){
691
                                index=this.solvedFacilities.size();
692
                                this.addSolvedFacility(index, flag);
693
                        }
694
                }
695
        }
696
        
697
        private void addSortedSolvedRoute(GvFlag flag, Route route) throws IndexOutOfBoundsException{
698
                boolean added=false;
699
                double routeCost=route.getCost();
700
                int index=0;
701
                if(routeCost<=this.facilitiesMaxLimit && this.solvedFacilities.size()<this.maxFacilitiesNumber){
702
                        for (index = 0; !added && index < this.solvedFacilities.size(); index++) {
703
                                if(routeCost<=((GvFlag)this.solvedFacilities.get(index)).getCost()){
704
                                        this.addSolvedFacility(index, flag);
705
                                        this.solvedRoutes.put(String.valueOf(index), route);
706
                                        added=true;
707
                                }
708
                        }
709

    
710
                        if(!added){
711
                                index=this.solvedFacilities.size();
712
                                this.addSolvedFacility(index, flag);
713
                                this.solvedRoutes.put(String.valueOf(index), route);
714
                        }
715
                }
716
        }
717
        
718
        private void addSolvedFacility(int index, GvFlag flag) throws IndexOutOfBoundsException{
719
                this.solvedFacilities.add(index, flag);
720
                this.informListeners(SOLVEDFACILITY_ADDED, flag, null);
721
        }
722
        
723
        /**
724
         * Gets the facility stored in the specified index. Remember that the solved facilities are stored in sorted mode, from the closest to the farthest
725
         * @param index the position where is the facility
726
         * @return the facility
727
         * @throws IndexOutOfBoundsException when the index is less than 0 and bigger than the facilities number 
728
         */
729
        public GvFlag getSolvedFacility(int index) throws IndexOutOfBoundsException{
730
                return (GvFlag)this.solvedFacilities.get(index);
731
        }
732
        
733
        /**
734
         * Gets the event used to generate the solution
735
         * @return the event used to generate the solution
736
         */
737
        public GvFlag getSolvedEvent(){
738
                return this.solutionEventSelected;
739
        }
740
        
741
        private Route calculateRoute(Network network, GvFlag source, GvFlag destination) throws GraphException{
742
                logger.info("Calculando ruta desde "+source+" hasta "+destination);
743
                long iniTime=System.currentTimeMillis();
744
                ShortestPathSolverAStar solverToEvent=new ShortestPathSolverAStar();
745
                //this.network.setLayer(lyr);
746
                //this.network.setGraph(g);
747
                solverToEvent.setNetwork(network);
748
                String fieldStreetName = (String) network.getLayer().getProperty("network_fieldStreetName");
749
                solverToEvent.setFielStreetName(fieldStreetName);
750

    
751

    
752
                Route route=null;
753
                network.removeFlags();
754
                network.addFlag(source);
755
                network.addFlag(destination);
756
                route=solverToEvent.calculateRoute();
757
                network.removeFlags();
758
                source.setCost(route.getCost());
759
                logger.info("Ruta desde "+source+" hasta "+destination+" calculada en "+(System.currentTimeMillis()-iniTime)+" millis");
760
                return route;
761
        }
762
        
763
        /**
764
         * Gets the route stored in the specified index. If the route doesn't exist it will be created with the source event specified when the route was solved and the facility that correspond to the route. Then, when the route is created, is stored for future accesses.
765
         * @param index the position where is the route
766
         * @return the route
767
         * @throws GraphException
768
         * @throws IndexOutOfBoundsException when the specified index is less than 0 and bigger than the number of solved facilities
769
         */
770
        public Route getSolvedRoute(int index) throws GraphException, IndexOutOfBoundsException{
771
                Route route=null;
772
                try{
773
                        route=(Route)this.solvedRoutes.get(String.valueOf(index));
774
                        logger.info("Ruta \""+route+"\" obtenida de la coleccion");
775
                }
776
                catch(IndexOutOfBoundsException except){
777
                        route=null;
778
                }
779
                if(route==null){
780
                        GvFlag facility=this.getSolvedFacility(index);
781
                        GvFlag source, destination;
782
                        if(this.solutionFromEventSelected){
783
                                source=this.solutionEventSelected;
784
                                destination=facility;
785
                        }
786
                        else{
787
                                source=facility;
788
                                destination=this.solutionEventSelected;
789
                        }
790
                        
791
                        GvFlag[] flags=this.getNetworkEvents(this.network);
792
                        route=this.calculateRoute(this.network, source, destination);
793
                        this.restoreNetworkEvents(this.network, flags);
794
                        this.solvedRoutes.put(String.valueOf(index), route);
795
                }
796
                
797
                return route;
798
        }
799
        
800
        /**
801
         * Draws the route over the network
802
         * @param route the route that will be draw
803
         */
804
        public void drawRouteOnGraphics(Route route){ 
805
                NetworkUtils.clearRouteFromGraphics(this.mpCtrl);
806
                
807
                NetworkUtils.drawRouteOnGraphics(this.mpCtrl, route);
808
                this.mpCtrl.drawMap(false);
809
        }
810
        
811
        /**
812
         * Shows a frame with the instructions of the route
813
         * @param route the route with the instructions to be shown
814
         */
815
        public void showRouteReport(Route route) {
816
                RouteReportPanel routeReport=new RouteReportPanel(route, this.mpCtrl);
817
                List reportsPanels = (List) GvSession.getInstance().get(this.mpCtrl, "RouteReport");
818
                if(reportsPanels == null){
819
                        reportsPanels = new ArrayList();
820
                        GvSession.getInstance().put(this.mpCtrl, "RouteReport", reportsPanels);
821
                } 
822
                reportsPanels.add(routeReport);
823
                RouteControlPanel controlPanel = (RouteControlPanel) GvSession.getInstance().get(this.mpCtrl, "RouteControlPanel");
824
                if (controlPanel != null)
825
                        controlPanel.refresh();
826

    
827
                PluginServices.getMDIManager().addWindow(routeReport);
828
        }
829
        
830
        /**
831
         * @return the number of solved facilities
832
         */
833
        public int getSolvedFacilitiesCount(){
834
                return this.solvedFacilities.size();
835
        }
836
        
837
        private void removeSolvedFacilities(){
838
                this.solvedFacilities=new ArrayList(this.maxFacilitiesNumber);
839
                this.solvedRoutes=new Hashtable();
840
                this.informListeners(SOLVEDFACILITIES_REMOVED, null, null);
841
        }
842
        
843
        /**
844
         * Gives all the facilities sorted by the cost field from closest to farthest
845
         * @return all the facilities
846
         */
847
        public Iterator getSortedSolvedFacilities(){
848
                return this.solvedFacilities.iterator();
849
        }
850
        
851
        /**
852
         * Gives all the routes sorted by the cost field from closest to farthest
853
         * @return all the routes
854
         */
855
        public Iterator getSortedSolvedRoutes(){
856
                return this.solvedRoutes.values().iterator();
857
        }
858
        
859

    
860
        /**
861
         * Shows an animation wich points with a circle to the position where is the flag
862
         * @param flag the pointed flag
863
         * @param color the color of the circle wich will point the flag
864
         * @param maxCount level of transparency of the circle
865
         */
866
        public void flashFlag(GvFlag flag, Color color, int maxCount) {
867
                NetworkUtils.flashPoint(this.mpCtrl, color, maxCount, flag.getOriginalPoint().getX(), flag.getOriginalPoint().getY());        
868
        }
869
        
870
        /**
871
         * Clear the flashes in the graphics
872
         */
873
        public void clearFlashes(){
874
                this.mpCtrl.repaint();
875
        }
876

    
877
        /* (non-Javadoc)
878
         * @see org.gvsig.graph.core.IFlagListener#flagsChanged(int)
879
         */
880
        public void flagsChanged(int reason) {
881
                switch(reason){
882
                        case IFlagListener.FLAG_ADDED:
883
                                this.informListeners(EVENT_ADDED, null, null);
884
                                break;
885
                        case IFlagListener.FLAG_REMOVED:
886
                                this.informListeners(EVENT_REMOVED, null, null);
887
                                break;
888
                }
889
                this.mpCtrl.drawMap(false);
890
        }
891
        
892
        private GvFlag[] getNetworkEvents(Network network) {
893
                return network.getFlags();
894
        }
895
        
896
        private void restoreNetworkEvents(Network network, GvFlag[] events){
897
                for (int i = 0; i < events.length; i++) {
898
                        network.addFlag(events[i]);
899
                }
900
        }
901
        
902
        /**
903
         * Finds and stores in sorted mode the closest facilities. Cost field is used to sort the facilities from the closest to the farthest. 
904
         * @throws GraphException
905
         * @throws ReadDriverException
906
         */
907
        public void solve() throws GraphException, ReadDriverException{
908
                this.solutionEventSelected=this.sourceEvent;
909
                this.solutionFromEventSelected=!this.toEvent;
910
                
911
                long initialTime=System.currentTimeMillis();
912
                this.network.removeFlagListener(this);
913
                this.events=this.getNetworkEvents(this.network);
914
                this.network.removeFlags();
915
                this.removeSolvedFacilities();
916
                if(this.facilities.size()>0){
917
                        this.maxFacilitiesNumber=(this.maxFacilitiesNumber<=0 || this.maxFacilitiesNumber>this.toolMaxFacilitiesNumber)? this.toolMaxFacilitiesNumber : this.maxFacilitiesNumber;
918
                        this.facilitiesMaxLimit=(this.facilitiesMaxLimit<=0)? Double.MAX_VALUE : this.facilitiesMaxLimit;
919
                        if(this.getSourceEvent()!=null){
920
                                if(this.toEvent){
921
                                        ShortestPathSolverAStar solverToEvent=new ShortestPathSolverAStar();
922
                                        //this.network.setLayer(lyr);
923
                                        //this.network.setGraph(g);
924
                                        solverToEvent.setNetwork(this.network);
925

    
926
                                        Iterator it=this.facilities.values().iterator();
927
                                        GvFlag flag=null;
928
                                        Route route=null;
929
                                        while(it.hasNext() && this.solvedFacilities.size()<this.maxFacilitiesNumber) {
930
                                                flag=(GvFlag)it.next();
931
                                                route=this.calculateRoute(this.network, flag, this.solutionEventSelected);
932
                                                if(route.getCost()<=this.facilitiesMaxLimit)
933
                                                        flag.setCost(route.getCost());
934
                                                        this.addSortedSolvedRoute(flag, route);
935
                                        }
936
                                }
937
                                else{
938
                                        OneToManySolver solverFromEvent = new OneToManySolver();
939
                                        //this.network.setLayer(lyr);
940
                                        //this.network.setGraph(g);
941
                                        solverFromEvent.setNetwork(this.network);
942

    
943
                                        this.network.addFlag(this.getSourceEvent());
944
                                        solverFromEvent.setSourceFlag(this.getSourceEvent());
945

    
946
                                        Iterator it=this.facilities.values().iterator();
947
                                        while(it.hasNext()) {
948
                                                this.network.addFlag((GvFlag)it.next());
949
                                        }
950
                                        solverFromEvent.putDestinationsOnNetwork(this.network.getFlags());
951

    
952
                                        solverFromEvent.setExploreAllNetwork(false);
953
                                        solverFromEvent.setMaxCost(this.facilitiesMaxLimit);
954
                                        solverFromEvent.calculate();
955
                                        solverFromEvent.removeDestinationsFromNetwork(this.network.getFlags());
956

    
957
                                        GvFlag[] solvedFlags=this.network.getFlags();
958
                                        for (int i = 1; i < solvedFlags.length; i++) {
959
                                                this.addSortedSolvedFacility(solvedFlags[i]);
960
                                        }
961
                                }
962
                        }
963
                }
964
                this.network.removeFlags();
965
                this.restoreNetworkEvents(this.network, this.events);
966
                this.network.addFlagListener(this);
967
                logger.info("Soluci?n obtenida en: "+(System.currentTimeMillis()-initialTime)+" millis");
968
        }
969
}