root / trunk / extensions / extGraph / src / org / gvsig / graph / ConnectivityExtension.java @ 29993
History | View | Annotate | Download (11.4 KB)
1 | 29800 | fpenarrubia | /* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
---|---|---|---|
2 | *
|
||
3 | * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
|
||
4 | *
|
||
5 | * This program is free software; you can redistribute it and/or
|
||
6 | * modify it under the terms of the GNU General Public License
|
||
7 | * as published by the Free Software Foundation; either version 2
|
||
8 | * of the License, or (at your option) any later version.
|
||
9 | *
|
||
10 | * This program is distributed in the hope that it will be useful,
|
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
13 | * GNU General Public License for more details.
|
||
14 | *
|
||
15 | * You should have received a copy of the GNU General Public License
|
||
16 | * along with this program; if not, write to the Free Software
|
||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
||
18 | *
|
||
19 | * For more information, contact:
|
||
20 | *
|
||
21 | * Generalitat Valenciana
|
||
22 | * Conselleria d'Infraestructures i Transport
|
||
23 | * Av. Blasco Ib??ez, 50
|
||
24 | * 46010 VALENCIA
|
||
25 | * SPAIN
|
||
26 | *
|
||
27 | * +34 963862235
|
||
28 | * gvsig@gva.es
|
||
29 | * www.gvsig.gva.es
|
||
30 | *
|
||
31 | * or
|
||
32 | *
|
||
33 | * IVER T.I. S.A
|
||
34 | * Salamanca 50
|
||
35 | * 46005 Valencia
|
||
36 | * Spain
|
||
37 | *
|
||
38 | * +34 963163400
|
||
39 | * dac@iver.es
|
||
40 | */
|
||
41 | package org.gvsig.graph; |
||
42 | |||
43 | import java.awt.Color; |
||
44 | import java.text.NumberFormat; |
||
45 | import java.util.Arrays; |
||
46 | import java.util.Random; |
||
47 | |||
48 | import javax.swing.ImageIcon; |
||
49 | import javax.swing.JOptionPane; |
||
50 | |||
51 | import org.gvsig.exceptions.BaseException; |
||
52 | 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.ConnectivityControlPanel; |
||
59 | import org.gvsig.graph.gui.wizard.servicearea.ServiceAreaWizard; |
||
60 | import org.gvsig.graph.solvers.EdgesMemoryDriver; |
||
61 | import org.gvsig.graph.solvers.OneToManySolver; |
||
62 | import org.gvsig.graph.solvers.ServiceAreaExtractor; |
||
63 | import org.gvsig.graph.solvers.ServiceAreaExtractor2; |
||
64 | |||
65 | import com.hardcode.gdbms.driver.exceptions.ReadDriverException; |
||
66 | import com.hardcode.gdbms.engine.values.DoubleValue; |
||
67 | import com.hardcode.gdbms.engine.values.ValueFactory; |
||
68 | import com.iver.andami.PluginServices; |
||
69 | import com.iver.andami.plugins.Extension; |
||
70 | import com.iver.andami.ui.mdiManager.IWindow; |
||
71 | import com.iver.cit.gvsig.fmap.MapContext; |
||
72 | import com.iver.cit.gvsig.fmap.MapControl; |
||
73 | import com.iver.cit.gvsig.fmap.core.FShape; |
||
74 | import com.iver.cit.gvsig.fmap.core.IGeometry; |
||
75 | import com.iver.cit.gvsig.fmap.core.ShapeFactory; |
||
76 | import com.iver.cit.gvsig.fmap.core.SymbologyFactory; |
||
77 | import com.iver.cit.gvsig.fmap.core.symbols.IFillSymbol; |
||
78 | import com.iver.cit.gvsig.fmap.core.symbols.ISymbol; |
||
79 | import com.iver.cit.gvsig.fmap.core.v02.FConstant; |
||
80 | import com.iver.cit.gvsig.fmap.core.v02.FLabel; |
||
81 | import com.iver.cit.gvsig.fmap.core.v02.FSymbol; |
||
82 | import com.iver.cit.gvsig.fmap.layers.FLayer; |
||
83 | import com.iver.cit.gvsig.fmap.layers.FLyrVect; |
||
84 | import com.iver.cit.gvsig.fmap.layers.GraphicLayer; |
||
85 | import com.iver.cit.gvsig.fmap.layers.LayerFactory; |
||
86 | import com.iver.cit.gvsig.fmap.layers.SingleLayerIterator; |
||
87 | import com.iver.cit.gvsig.fmap.rendering.FGraphic; |
||
88 | import com.iver.cit.gvsig.fmap.rendering.FGraphicLabel; |
||
89 | import com.iver.cit.gvsig.fmap.rendering.IVectorialUniqueValueLegend; |
||
90 | import com.iver.cit.gvsig.fmap.rendering.LegendFactory; |
||
91 | import com.iver.cit.gvsig.project.documents.view.gui.View; |
||
92 | |||
93 | /**
|
||
94 | * @author fjp
|
||
95 | *
|
||
96 | * Extension to perform Connectivity calculations.
|
||
97 | * The user can put a flag and select a point associated layer, and set
|
||
98 | * if he wants to use a max cost and/or max distance.
|
||
99 | * The algorithm will explore the network in reverse order or in normal order and
|
||
100 | * the arcs reached will be selected. If the user selects an associated layer, the
|
||
101 | * points reached will be selected also.
|
||
102 | * This may be useful in the following situations:
|
||
103 | * 1.- Searching for connectivity. The unconnected parts of the network will be unselected.
|
||
104 | * 2.- Selecting points connected to the network and affected by a cut in the graph
|
||
105 | * 3.- Using reverse order, you may find the closest valve to close and avoid leaks.
|
||
106 | */
|
||
107 | public class ConnectivityExtension extends Extension { |
||
108 | |||
109 | private int idSymbolLine = -1; |
||
110 | |||
111 | public void initialize() { |
||
112 | PluginServices.getIconTheme().registerDefault( |
||
113 | "connectivity",
|
||
114 | this.getClass().getClassLoader().getResource("images/connectivity.gif") |
||
115 | ); |
||
116 | |||
117 | } |
||
118 | |||
119 | public void execute(String actionCommand) { |
||
120 | |||
121 | View v = (View) PluginServices.getMDIManager().getActiveWindow(); |
||
122 | MapControl mapCtrl = v.getMapControl(); |
||
123 | MapContext map = mapCtrl.getMapContext(); |
||
124 | SingleLayerIterator it = new SingleLayerIterator(map.getLayers());
|
||
125 | while (it.hasNext()) {
|
||
126 | FLayer aux = it.next(); |
||
127 | if (!aux.isActive())
|
||
128 | continue;
|
||
129 | Network net = (Network) aux.getProperty("network");
|
||
130 | |||
131 | if (net != null) { |
||
132 | if(actionCommand.equals("CONNECTIVITY")){ |
||
133 | ImageIcon icon = new ImageIcon(this.getClass().getClassLoader() |
||
134 | .getResource("images/wizard_connectivity.png"));
|
||
135 | ConnectivityControlPanel w =new ConnectivityControlPanel();
|
||
136 | try {
|
||
137 | w.setMapControl(mapCtrl); |
||
138 | PluginServices.getMDIManager().addWindow(w); |
||
139 | } catch (ReadDriverException e) {
|
||
140 | // TODO Auto-generated catch block
|
||
141 | e.printStackTrace(); |
||
142 | } |
||
143 | |||
144 | } |
||
145 | return;
|
||
146 | } |
||
147 | } |
||
148 | |||
149 | } |
||
150 | |||
151 | /**
|
||
152 | * @param mapCtrl
|
||
153 | * @param map
|
||
154 | * @param net
|
||
155 | * @param flags
|
||
156 | * @param solver
|
||
157 | * @return
|
||
158 | * @throws GraphException
|
||
159 | */
|
||
160 | private void calculateLabels(MapControl mapCtrl, MapContext map, Network net, GvFlag[] flags, OneToManySolver solver) throws GraphException { |
||
161 | GraphicLayer graphicLayer = mapCtrl.getMapContext() |
||
162 | .getGraphicsLayer(); |
||
163 | removeOldLabels(graphicLayer); |
||
164 | for (int i = 0; i < flags.length; i++) { |
||
165 | |||
166 | solver.setSourceFlag(flags[i]); |
||
167 | long t1 = System.currentTimeMillis(); |
||
168 | solver.setExploreAllNetwork(true);
|
||
169 | solver.calculate(); |
||
170 | long t2 = System.currentTimeMillis(); |
||
171 | System.out.println("Punto " + i + " de " |
||
172 | + flags.length + ". " + (t2 - t1)
|
||
173 | + " msecs.");
|
||
174 | // Despu?s de esto, los nodos de la red est?n
|
||
175 | // etiquetados con los costes al nodo or?gen
|
||
176 | EdgesMemoryDriver driver = new EdgesMemoryDriver(net);
|
||
177 | FLayer lyr = LayerFactory.createLayer("Edges", driver, null); |
||
178 | map.getLayers().addLayer(lyr); |
||
179 | // doLabeling(mapCtrl, net, flags[i]);
|
||
180 | |||
181 | } |
||
182 | |||
183 | } |
||
184 | |||
185 | private void calculateServiceArea(MapContext map, Network net, GvFlag[] flags, OneToManySolver solver) throws BaseException { |
||
186 | ServiceAreaExtractor2 extractor = new ServiceAreaExtractor2(net);
|
||
187 | String aux = JOptionPane.showInputDialog("Por favor, introduzca el coste m?ximo del ?rea de servicio:"); |
||
188 | if (aux == null) |
||
189 | return;
|
||
190 | double[] costs = NetworkUtils.string2doubleArray(aux, ","); |
||
191 | Arrays.sort(costs);
|
||
192 | solver.addListener(extractor); |
||
193 | for (int i = 0; i < flags.length; i++) { |
||
194 | solver.setSourceFlag(flags[i]); |
||
195 | long t1 = System.currentTimeMillis(); |
||
196 | solver.setExploreAllNetwork(true);
|
||
197 | // TODO: El coste m?ximo deber?a ser un array de costes m?ximos
|
||
198 | // para obtener varios pol?gonos por cada intervalo. Y 2 opciones m?s:
|
||
199 | // Si se desea ?rea compacta y
|
||
200 | // Si los pol?gonos se quieren como anillos conc?ntricos.
|
||
201 | // Cada Flag deber?a tener asociado un array de costes m?ximos o distancias
|
||
202 | solver.setMaxCost(costs[costs.length -1]);
|
||
203 | extractor.setIdFlag(i); |
||
204 | extractor.setCosts(costs); |
||
205 | |||
206 | extractor.setDoCompactArea(true);
|
||
207 | |||
208 | solver.calculate(); |
||
209 | long t2 = System.currentTimeMillis(); |
||
210 | System.out.println("Punto " + i + " de " |
||
211 | + flags.length + ". " + (t2 - t1)
|
||
212 | + " msecs.");
|
||
213 | extractor.writeServiceArea(); |
||
214 | |||
215 | } |
||
216 | extractor.closeFiles(); |
||
217 | FLyrVect lyrPol = extractor.getPolygonLayer(); |
||
218 | lyrPol.setProjection(map.getProjection()); |
||
219 | IVectorialUniqueValueLegend defaultLegend = LegendFactory.createVectorialUniqueValueLegend(FShape.POLYGON); |
||
220 | defaultLegend.setClassifyingFieldNames(new String[] {"COST"} ); |
||
221 | ISymbol myDefaultSymbol = SymbologyFactory. |
||
222 | createDefaultSymbolByShapeType(FShape.POLYGON); |
||
223 | |||
224 | defaultLegend.setDefaultSymbol(myDefaultSymbol); |
||
225 | |||
226 | DoubleValue clave; |
||
227 | IFillSymbol theSymbol = null;
|
||
228 | Random rnd = new Random(System.currentTimeMillis()); |
||
229 | |||
230 | for (int j = 0; j < costs.length; j++) { |
||
231 | clave = ValueFactory.createValue(costs[j]); |
||
232 | if (defaultLegend.getSymbolByValue(clave) == null) { |
||
233 | theSymbol = (IFillSymbol) SymbologyFactory. |
||
234 | createDefaultSymbolByShapeType(FShape.POLYGON); |
||
235 | theSymbol.setDescription(clave.toString()); |
||
236 | Color newColor = new Color(rnd.nextFloat(), |
||
237 | rnd.nextFloat(), |
||
238 | rnd.nextFloat(), 0.7f);
|
||
239 | theSymbol.setFillColor(newColor); |
||
240 | |||
241 | defaultLegend.addSymbol(clave, theSymbol); |
||
242 | } |
||
243 | |||
244 | } // for
|
||
245 | lyrPol.setLegend(defaultLegend); |
||
246 | |||
247 | FLyrVect lyrLine = extractor.getLineLayer(); |
||
248 | lyrLine.setProjection(map.getProjection()); |
||
249 | |||
250 | // provisional
|
||
251 | FLyrVect lyrPoints= extractor.getBorderPoints(); |
||
252 | lyrPoints.setProjection(map.getProjection()); |
||
253 | |||
254 | map.beginAtomicEvent(); |
||
255 | map.getLayers().addLayer(lyrPol); |
||
256 | map.getLayers().addLayer(lyrLine); |
||
257 | map.getLayers().addLayer(lyrPoints); |
||
258 | map.endAtomicEvent(); |
||
259 | |||
260 | |||
261 | } |
||
262 | |||
263 | private FSymbol getTextSymbol() {
|
||
264 | FSymbol theSymbol = new FSymbol(FConstant.SYMBOL_TYPE_TEXT);
|
||
265 | theSymbol.setColor(Color.RED);
|
||
266 | theSymbol.setStyle(FConstant.SYMBOL_STYLE_MARKER_CIRCLE); |
||
267 | theSymbol.setFontColor(Color.BLACK);
|
||
268 | theSymbol.setSizeInPixels(true);
|
||
269 | theSymbol.setSize(9);
|
||
270 | return theSymbol;
|
||
271 | } |
||
272 | |||
273 | private void removeOldLabels(GraphicLayer gLyr) { |
||
274 | for (int i = gLyr.getNumGraphics() - 1; i >= 0; i--) { |
||
275 | FGraphic gr = gLyr.getGraphic(i); |
||
276 | if (gr.equals("N")) |
||
277 | gLyr.removeGraphic(i); |
||
278 | |||
279 | } |
||
280 | } |
||
281 | |||
282 | private void doLabeling(MapControl mapControl, Network net, GvFlag flag) { |
||
283 | GraphicLayer graphicLayer = mapControl.getMapContext() |
||
284 | .getGraphicsLayer(); |
||
285 | IGraph g = net.getGraph(); |
||
286 | int idSymbol = graphicLayer.addSymbol(getTextSymbol());
|
||
287 | String tag = "N"; |
||
288 | for (int i = 0; i < g.numVertices(); i++) { |
||
289 | GvNode node = g.getNodeByID(i); |
||
290 | IGeometry geom = ShapeFactory.createPoint2D(node.getX(), node |
||
291 | .getY()); |
||
292 | NumberFormat nf = NumberFormat.getInstance(); |
||
293 | nf.setMaximumFractionDigits(1);
|
||
294 | String aux = "\u221E"; // infinito |
||
295 | if (node.getBestCost() < Double.MAX_VALUE) |
||
296 | aux = nf.format(node.getBestCost()) + " - " + nf.format(node.getAccumulatedLength());
|
||
297 | FGraphicLabel theGLabel = new FGraphicLabel(geom, idSymbol, aux);
|
||
298 | theGLabel.setObjectTag(tag); |
||
299 | theGLabel.getLabel().setJustification(FLabel.CENTER_TOP); |
||
300 | graphicLayer.addGraphic(theGLabel); |
||
301 | } |
||
302 | mapControl.drawGraphics(); |
||
303 | |||
304 | } |
||
305 | |||
306 | public boolean isEnabled() { |
||
307 | IWindow window = PluginServices.getMDIManager().getActiveWindow(); |
||
308 | if (window instanceof View) |
||
309 | { |
||
310 | View v = (View) window; |
||
311 | MapControl mapCtrl = v.getMapControl(); |
||
312 | MapContext map = mapCtrl.getMapContext(); |
||
313 | |||
314 | SingleLayerIterator it = new SingleLayerIterator(map.getLayers());
|
||
315 | while (it.hasNext())
|
||
316 | { |
||
317 | FLayer aux = it.next(); |
||
318 | if (!aux.isActive())
|
||
319 | continue;
|
||
320 | Network net = (Network) aux.getProperty("network");
|
||
321 | |||
322 | if ( net != null) |
||
323 | { |
||
324 | 29993 | fpenarrubia | return true; |
325 | 29800 | fpenarrubia | } |
326 | } |
||
327 | } |
||
328 | return false; |
||
329 | } |
||
330 | |||
331 | public boolean isVisible() { |
||
332 | IWindow f = PluginServices.getMDIManager() |
||
333 | .getActiveWindow(); |
||
334 | if (f == null) { |
||
335 | return false; |
||
336 | } |
||
337 | if (f instanceof View) { |
||
338 | return true; |
||
339 | } |
||
340 | return false; |
||
341 | |||
342 | } |
||
343 | |||
344 | } |