svn-gvsig-desktop / trunk / extensions / extGraph / src / org / gvsig / graph / ServiceAreaExtension.java @ 29994
History | View | Annotate | Download (12.3 KB)
1 | 13583 | fjp | /* 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 | 22182 | fpenarrubia | package org.gvsig.graph; |
42 | 13583 | fjp | |
43 | import java.awt.Color; |
||
44 | import java.text.NumberFormat; |
||
45 | 14712 | fpenarrubia | import java.util.Arrays; |
46 | 15909 | fpenarrubia | import java.util.Random; |
47 | 13583 | fjp | |
48 | 17628 | falario | import javax.swing.ImageIcon; |
49 | 13583 | fjp | import javax.swing.JOptionPane; |
50 | |||
51 | 14459 | fpenarrubia | import org.gvsig.exceptions.BaseException; |
52 | 22182 | fpenarrubia | import org.gvsig.graph.core.GraphException; |
53 | import org.gvsig.graph.core.GvFlag; |
||
54 | import org.gvsig.graph.core.GvNode; |
||
55 | import org.gvsig.graph.core.IGraph; |
||
56 | import org.gvsig.graph.core.Network; |
||
57 | import org.gvsig.graph.core.NetworkUtils; |
||
58 | import org.gvsig.graph.gui.wizard.servicearea.ServiceAreaWizard; |
||
59 | import org.gvsig.graph.solvers.EdgesMemoryDriver; |
||
60 | import org.gvsig.graph.solvers.OneToManySolver; |
||
61 | 25359 | fpenarrubia | import org.gvsig.graph.solvers.ServiceAreaExtractor; |
62 | 22182 | fpenarrubia | import org.gvsig.graph.solvers.ServiceAreaExtractor2; |
63 | 14459 | fpenarrubia | |
64 | 15909 | fpenarrubia | import com.hardcode.gdbms.engine.values.DoubleValue; |
65 | import com.hardcode.gdbms.engine.values.ValueFactory; |
||
66 | 13583 | fjp | import com.iver.andami.PluginServices; |
67 | import com.iver.andami.plugins.Extension; |
||
68 | import com.iver.andami.ui.mdiManager.IWindow; |
||
69 | import com.iver.cit.gvsig.fmap.MapContext; |
||
70 | import com.iver.cit.gvsig.fmap.MapControl; |
||
71 | 15909 | fpenarrubia | import com.iver.cit.gvsig.fmap.core.FShape; |
72 | 13583 | fjp | import com.iver.cit.gvsig.fmap.core.IGeometry; |
73 | import com.iver.cit.gvsig.fmap.core.ShapeFactory; |
||
74 | 15909 | fpenarrubia | import com.iver.cit.gvsig.fmap.core.SymbologyFactory; |
75 | import com.iver.cit.gvsig.fmap.core.symbols.IFillSymbol; |
||
76 | import com.iver.cit.gvsig.fmap.core.symbols.ISymbol; |
||
77 | 13583 | fjp | import com.iver.cit.gvsig.fmap.core.v02.FConstant; |
78 | import com.iver.cit.gvsig.fmap.core.v02.FLabel; |
||
79 | import com.iver.cit.gvsig.fmap.core.v02.FSymbol; |
||
80 | import com.iver.cit.gvsig.fmap.layers.FLayer; |
||
81 | 14459 | fpenarrubia | import com.iver.cit.gvsig.fmap.layers.FLyrVect; |
82 | 13583 | fjp | import com.iver.cit.gvsig.fmap.layers.GraphicLayer; |
83 | import com.iver.cit.gvsig.fmap.layers.LayerFactory; |
||
84 | import com.iver.cit.gvsig.fmap.layers.SingleLayerIterator; |
||
85 | import com.iver.cit.gvsig.fmap.rendering.FGraphic; |
||
86 | import com.iver.cit.gvsig.fmap.rendering.FGraphicLabel; |
||
87 | 15909 | fpenarrubia | import com.iver.cit.gvsig.fmap.rendering.IVectorialUniqueValueLegend; |
88 | import com.iver.cit.gvsig.fmap.rendering.LegendFactory; |
||
89 | 13583 | fjp | import com.iver.cit.gvsig.project.documents.view.gui.View; |
90 | |||
91 | /**
|
||
92 | * @author fjp
|
||
93 | *
|
||
94 | * Extension to perform ServiceArea calculations. Here you will find code to:
|
||
95 | * 1.- See the distances to every node on the network to one or many point
|
||
96 | * sources. 2.- TODO: Calculate a polyline layer with costs and length
|
||
97 | * calculated to nearest source point. 3.- TODO: Calculate polygons covering
|
||
98 | * those service areas.
|
||
99 | */
|
||
100 | public class ServiceAreaExtension extends Extension { |
||
101 | |||
102 | private int idSymbolLine = -1; |
||
103 | |||
104 | public void initialize() { |
||
105 | 15909 | fpenarrubia | PluginServices.getIconTheme().registerDefault( |
106 | "service_area",
|
||
107 | this.getClass().getClassLoader().getResource("images/service_area.png") |
||
108 | 17628 | falario | ); |
109 | 15909 | fpenarrubia | |
110 | 17628 | falario | PluginServices.getIconTheme().registerDefault( |
111 | "service_area_wrong_costs",
|
||
112 | this.getClass().getClassLoader().getResource("images/service_area_wrong_costs.png")); |
||
113 | |||
114 | PluginServices.getIconTheme().registerDefault( |
||
115 | "service_area_compact",
|
||
116 | this.getClass().getClassLoader().getResource("images/service_area_compact.png")); |
||
117 | |||
118 | PluginServices.getIconTheme().registerDefault( |
||
119 | "service_area_convex",
|
||
120 | this.getClass().getClassLoader().getResource("images/service_area_convex.png")); |
||
121 | |||
122 | PluginServices.getIconTheme().registerDefault( |
||
123 | "service_area_fusion",
|
||
124 | this.getClass().getClassLoader().getResource("images/service_area_fusion.png")); |
||
125 | |||
126 | PluginServices.getIconTheme().registerDefault( |
||
127 | "service_area_non_fusion",
|
||
128 | this.getClass().getClassLoader().getResource("images/service_area_non_fusion.png")); |
||
129 | |||
130 | PluginServices.getIconTheme().registerDefault( |
||
131 | "service_area_disks",
|
||
132 | this.getClass().getClassLoader().getResource("images/service_area_disks.png")); |
||
133 | |||
134 | PluginServices.getIconTheme().registerDefault( |
||
135 | "service_area_rings",
|
||
136 | this.getClass().getClassLoader().getResource("images/service_area_rings.png")); |
||
137 | 13583 | fjp | } |
138 | |||
139 | public void execute(String actionCommand) { |
||
140 | |||
141 | View v = (View) PluginServices.getMDIManager().getActiveWindow(); |
||
142 | MapControl mapCtrl = v.getMapControl(); |
||
143 | MapContext map = mapCtrl.getMapContext(); |
||
144 | 14459 | fpenarrubia | SingleLayerIterator it = new SingleLayerIterator(map.getLayers());
|
145 | while (it.hasNext()) {
|
||
146 | FLayer aux = it.next(); |
||
147 | if (!aux.isActive())
|
||
148 | continue;
|
||
149 | Network net = (Network) aux.getProperty("network");
|
||
150 | 13583 | fjp | |
151 | 14459 | fpenarrubia | if (net != null) { |
152 | GvFlag[] flags = net.getFlags();
|
||
153 | if (flags.length == 0) { |
||
154 | JOptionPane.showMessageDialog(null, |
||
155 | "Primero carga las paradas.");
|
||
156 | return;
|
||
157 | } |
||
158 | // setVelocities(net);
|
||
159 | try {
|
||
160 | OneToManySolver solver = new OneToManySolver();
|
||
161 | solver.setNetwork(net); |
||
162 | 24380 | fpenarrubia | solver.putDestinationsOnNetwork(net.getFlags()); |
163 | 14459 | fpenarrubia | if (actionCommand.equals("LABEL_NODE_DISTANCES")) { |
164 | calculateLabels(mapCtrl, map, net, flags, solver); |
||
165 | 13583 | fjp | } |
166 | 14459 | fpenarrubia | if (actionCommand.equals("SERVICE_AREA")) { |
167 | calculateServiceArea(map, net, flags, solver); |
||
168 | 17628 | falario | } |
169 | if(actionCommand.equals("PRUEBA_WIZARD_SERVICE_AREA")){ |
||
170 | ImageIcon icon = new ImageIcon(this.getClass().getClassLoader() |
||
171 | .getResource("images/service_area-wizard-logo.jpg"));
|
||
172 | ServiceAreaWizard wiz=new ServiceAreaWizard(icon, null); |
||
173 | PluginServices.getMDIManager().addWindow(wiz); |
||
174 | } |
||
175 | 24380 | fpenarrubia | solver.removeDestinationsFromNetwork(net.getFlags()); |
176 | 14459 | fpenarrubia | } catch (BaseException e) {
|
177 | // TODO Auto-generated catch block
|
||
178 | e.printStackTrace(); |
||
179 | } |
||
180 | 13583 | fjp | |
181 | 14459 | fpenarrubia | return;
|
182 | } |
||
183 | } |
||
184 | 13583 | fjp | |
185 | 14459 | fpenarrubia | } |
186 | 13583 | fjp | |
187 | 14459 | fpenarrubia | /**
|
188 | * @param mapCtrl
|
||
189 | * @param map
|
||
190 | * @param net
|
||
191 | * @param flags
|
||
192 | * @param solver
|
||
193 | * @return
|
||
194 | * @throws GraphException
|
||
195 | */
|
||
196 | private void calculateLabels(MapControl mapCtrl, MapContext map, Network net, GvFlag[] flags, OneToManySolver solver) throws GraphException { |
||
197 | GraphicLayer graphicLayer = mapCtrl.getMapContext() |
||
198 | .getGraphicsLayer(); |
||
199 | removeOldLabels(graphicLayer); |
||
200 | for (int i = 0; i < flags.length; i++) { |
||
201 | 13583 | fjp | |
202 | 14459 | fpenarrubia | solver.setSourceFlag(flags[i]); |
203 | long t1 = System.currentTimeMillis(); |
||
204 | solver.setExploreAllNetwork(true);
|
||
205 | solver.calculate(); |
||
206 | long t2 = System.currentTimeMillis(); |
||
207 | System.out.println("Punto " + i + " de " |
||
208 | + flags.length + ". " + (t2 - t1)
|
||
209 | + " msecs.");
|
||
210 | // Despu?s de esto, los nodos de la red est?n
|
||
211 | // etiquetados con los costes al nodo or?gen
|
||
212 | EdgesMemoryDriver driver = new EdgesMemoryDriver(net);
|
||
213 | FLayer lyr = LayerFactory.createLayer("Edges", driver, null); |
||
214 | map.getLayers().addLayer(lyr); |
||
215 | // doLabeling(mapCtrl, net, flags[i]);
|
||
216 | |||
217 | 13583 | fjp | } |
218 | 14459 | fpenarrubia | |
219 | } |
||
220 | 13583 | fjp | |
221 | 14459 | fpenarrubia | private void calculateServiceArea(MapContext map, Network net, GvFlag[] flags, OneToManySolver solver) throws BaseException { |
222 | 15509 | fpenarrubia | ServiceAreaExtractor2 extractor = new ServiceAreaExtractor2(net);
|
223 | 14459 | fpenarrubia | String aux = JOptionPane.showInputDialog("Por favor, introduzca el coste m?ximo del ?rea de servicio:"); |
224 | if (aux == null) |
||
225 | return;
|
||
226 | 14712 | fpenarrubia | double[] costs = NetworkUtils.string2doubleArray(aux, ","); |
227 | Arrays.sort(costs);
|
||
228 | 15509 | fpenarrubia | solver.addListener(extractor); |
229 | 14459 | fpenarrubia | for (int i = 0; i < flags.length; i++) { |
230 | solver.setSourceFlag(flags[i]); |
||
231 | long t1 = System.currentTimeMillis(); |
||
232 | solver.setExploreAllNetwork(true);
|
||
233 | // TODO: El coste m?ximo deber?a ser un array de costes m?ximos
|
||
234 | // para obtener varios pol?gonos por cada intervalo. Y 2 opciones m?s:
|
||
235 | // Si se desea ?rea compacta y
|
||
236 | // Si los pol?gonos se quieren como anillos conc?ntricos.
|
||
237 | // Cada Flag deber?a tener asociado un array de costes m?ximos o distancias
|
||
238 | 14712 | fpenarrubia | solver.setMaxCost(costs[costs.length -1]);
|
239 | 15509 | fpenarrubia | extractor.setIdFlag(i); |
240 | extractor.setCosts(costs); |
||
241 | 22687 | fpenarrubia | |
242 | 26237 | fpenarrubia | extractor.setDoCompactArea(true);
|
243 | 22687 | fpenarrubia | |
244 | 14459 | fpenarrubia | solver.calculate(); |
245 | long t2 = System.currentTimeMillis(); |
||
246 | System.out.println("Punto " + i + " de " |
||
247 | + flags.length + ". " + (t2 - t1)
|
||
248 | + " msecs.");
|
||
249 | 15509 | fpenarrubia | extractor.writeServiceArea(); |
250 | |||
251 | 14459 | fpenarrubia | } |
252 | 15509 | fpenarrubia | extractor.closeFiles(); |
253 | 14712 | fpenarrubia | FLyrVect lyrPol = extractor.getPolygonLayer(); |
254 | lyrPol.setProjection(map.getProjection()); |
||
255 | 15909 | fpenarrubia | IVectorialUniqueValueLegend defaultLegend = LegendFactory.createVectorialUniqueValueLegend(FShape.POLYGON); |
256 | defaultLegend.setClassifyingFieldNames(new String[] {"COST"} ); |
||
257 | ISymbol myDefaultSymbol = SymbologyFactory. |
||
258 | createDefaultSymbolByShapeType(FShape.POLYGON); |
||
259 | |||
260 | defaultLegend.setDefaultSymbol(myDefaultSymbol); |
||
261 | |||
262 | DoubleValue clave; |
||
263 | IFillSymbol theSymbol = null;
|
||
264 | Random rnd = new Random(System.currentTimeMillis()); |
||
265 | |||
266 | for (int j = 0; j < costs.length; j++) { |
||
267 | clave = ValueFactory.createValue(costs[j]); |
||
268 | if (defaultLegend.getSymbolByValue(clave) == null) { |
||
269 | theSymbol = (IFillSymbol) SymbologyFactory. |
||
270 | createDefaultSymbolByShapeType(FShape.POLYGON); |
||
271 | theSymbol.setDescription(clave.toString()); |
||
272 | Color newColor = new Color(rnd.nextFloat(), |
||
273 | rnd.nextFloat(), |
||
274 | rnd.nextFloat(), 0.7f);
|
||
275 | theSymbol.setFillColor(newColor); |
||
276 | |||
277 | defaultLegend.addSymbol(clave, theSymbol); |
||
278 | } |
||
279 | |||
280 | } // for
|
||
281 | lyrPol.setLegend(defaultLegend); |
||
282 | |||
283 | 14712 | fpenarrubia | FLyrVect lyrLine = extractor.getLineLayer(); |
284 | lyrLine.setProjection(map.getProjection()); |
||
285 | 25434 | fpenarrubia | |
286 | // provisional
|
||
287 | FLyrVect lyrPoints= extractor.getBorderPoints(); |
||
288 | lyrPoints.setProjection(map.getProjection()); |
||
289 | |||
290 | 14712 | fpenarrubia | map.beginAtomicEvent(); |
291 | map.getLayers().addLayer(lyrPol); |
||
292 | map.getLayers().addLayer(lyrLine); |
||
293 | 25434 | fpenarrubia | map.getLayers().addLayer(lyrPoints); |
294 | 14712 | fpenarrubia | map.endAtomicEvent(); |
295 | |||
296 | 14459 | fpenarrubia | |
297 | 13583 | fjp | } |
298 | 14459 | fpenarrubia | |
299 | 13583 | fjp | private FSymbol getTextSymbol() {
|
300 | FSymbol theSymbol = new FSymbol(FConstant.SYMBOL_TYPE_TEXT);
|
||
301 | theSymbol.setColor(Color.RED);
|
||
302 | theSymbol.setStyle(FConstant.SYMBOL_STYLE_MARKER_CIRCLE); |
||
303 | theSymbol.setFontColor(Color.BLACK);
|
||
304 | theSymbol.setSizeInPixels(true);
|
||
305 | theSymbol.setSize(9);
|
||
306 | return theSymbol;
|
||
307 | } |
||
308 | |||
309 | private void removeOldLabels(GraphicLayer gLyr) { |
||
310 | for (int i = gLyr.getNumGraphics() - 1; i >= 0; i--) { |
||
311 | FGraphic gr = gLyr.getGraphic(i); |
||
312 | if (gr.equals("N")) |
||
313 | gLyr.removeGraphic(i); |
||
314 | |||
315 | } |
||
316 | } |
||
317 | |||
318 | private void doLabeling(MapControl mapControl, Network net, GvFlag flag) { |
||
319 | GraphicLayer graphicLayer = mapControl.getMapContext() |
||
320 | .getGraphicsLayer(); |
||
321 | IGraph g = net.getGraph(); |
||
322 | int idSymbol = graphicLayer.addSymbol(getTextSymbol());
|
||
323 | String tag = "N"; |
||
324 | for (int i = 0; i < g.numVertices(); i++) { |
||
325 | GvNode node = g.getNodeByID(i); |
||
326 | IGeometry geom = ShapeFactory.createPoint2D(node.getX(), node |
||
327 | .getY()); |
||
328 | NumberFormat nf = NumberFormat.getInstance(); |
||
329 | nf.setMaximumFractionDigits(1);
|
||
330 | String aux = "\u221E"; // infinito |
||
331 | if (node.getBestCost() < Double.MAX_VALUE) |
||
332 | aux = nf.format(node.getBestCost()) + " - " + nf.format(node.getAccumulatedLength());
|
||
333 | FGraphicLabel theGLabel = new FGraphicLabel(geom, idSymbol, aux);
|
||
334 | theGLabel.setObjectTag(tag); |
||
335 | theGLabel.getLabel().setJustification(FLabel.CENTER_TOP); |
||
336 | graphicLayer.addGraphic(theGLabel); |
||
337 | } |
||
338 | mapControl.drawGraphics(); |
||
339 | |||
340 | } |
||
341 | |||
342 | public boolean isEnabled() { |
||
343 | IWindow window = PluginServices.getMDIManager().getActiveWindow(); |
||
344 | if (window instanceof View) |
||
345 | { |
||
346 | View v = (View) window; |
||
347 | MapControl mapCtrl = v.getMapControl(); |
||
348 | MapContext map = mapCtrl.getMapContext(); |
||
349 | |||
350 | SingleLayerIterator it = new SingleLayerIterator(map.getLayers());
|
||
351 | while (it.hasNext())
|
||
352 | { |
||
353 | FLayer aux = it.next(); |
||
354 | if (!aux.isActive())
|
||
355 | continue;
|
||
356 | Network net = (Network) aux.getProperty("network");
|
||
357 | |||
358 | if ( net != null) |
||
359 | { |
||
360 | 23588 | fpenarrubia | if (net.getFlags().length > 0) |
361 | { |
||
362 | return true; |
||
363 | } |
||
364 | 13583 | fjp | } |
365 | } |
||
366 | } |
||
367 | return false; |
||
368 | } |
||
369 | |||
370 | public boolean isVisible() { |
||
371 | IWindow f = PluginServices.getMDIManager() |
||
372 | .getActiveWindow(); |
||
373 | if (f == null) { |
||
374 | return false; |
||
375 | } |
||
376 | if (f instanceof View) { |
||
377 | return true; |
||
378 | } |
||
379 | return false; |
||
380 | |||
381 | } |
||
382 | |||
383 | } |