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 |
} |