svn-gvsig-desktop / tags / PilotoRedes_Build_4 / extensions / extGraph_predes / src / com / iver / cit / gvsig / graph / TopologyExtension.java @ 12191
History | View | Annotate | Download (12.2 KB)
1 | 8150 | 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 | package com.iver.cit.gvsig.graph; |
||
42 | |||
43 | import java.awt.Color; |
||
44 | import java.awt.geom.Rectangle2D; |
||
45 | import java.util.Collection; |
||
46 | import java.util.Iterator; |
||
47 | import java.util.Set; |
||
48 | |||
49 | import com.iver.andami.PluginServices; |
||
50 | import com.iver.andami.messages.NotificationManager; |
||
51 | import com.iver.andami.plugins.Extension; |
||
52 | import com.iver.andami.ui.mdiManager.IWindow; |
||
53 | import com.iver.cit.gvsig.fmap.DriverException; |
||
54 | import com.iver.cit.gvsig.fmap.MapControl; |
||
55 | import com.iver.cit.gvsig.fmap.core.FPoint2D; |
||
56 | import com.iver.cit.gvsig.fmap.core.FShape; |
||
57 | import com.iver.cit.gvsig.fmap.core.GeneralPathX; |
||
58 | import com.iver.cit.gvsig.fmap.core.IGeometry; |
||
59 | import com.iver.cit.gvsig.fmap.core.ShapeFactory; |
||
60 | import com.iver.cit.gvsig.fmap.core.v02.FConstant; |
||
61 | import com.iver.cit.gvsig.fmap.core.v02.FConverter; |
||
62 | import com.iver.cit.gvsig.fmap.core.v02.FSymbol; |
||
63 | import com.iver.cit.gvsig.fmap.drivers.DriverIOException; |
||
64 | import com.iver.cit.gvsig.fmap.layers.FBitSet; |
||
65 | import com.iver.cit.gvsig.fmap.layers.FLayer; |
||
66 | import com.iver.cit.gvsig.fmap.layers.FLyrVect; |
||
67 | import com.iver.cit.gvsig.fmap.layers.GraphicLayer; |
||
68 | import com.iver.cit.gvsig.fmap.rendering.FGraphic; |
||
69 | import com.iver.cit.gvsig.project.documents.view.gui.View; |
||
70 | 11091 | jaume | import com.iver.cit.gvsig.project.documents.view.toc.FLyrVectEditPropertiesTocMenuEntry2; |
71 | 8150 | fjp | import com.iver.cit.gvsig.topology.TopologyBuilder; |
72 | import com.iver.cit.gvsig.topology.triangulation.DelaunayTriangulation; |
||
73 | import com.iver.cit.gvsig.topology.triangulation.Pnt; |
||
74 | import com.iver.cit.gvsig.topology.triangulation.Simplex; |
||
75 | 11094 | jmvivo | import com.iver.utiles.extensionPoints.ExtensionPoint; |
76 | 11089 | jaume | import com.iver.utiles.extensionPoints.ExtensionPoints; |
77 | import com.iver.utiles.extensionPoints.ExtensionPointsSingleton; |
||
78 | 8150 | fjp | import com.vividsolutions.jts.geom.Coordinate; |
79 | import com.vividsolutions.jts.geom.CoordinateArrays; |
||
80 | import com.vividsolutions.jts.geom.Geometry; |
||
81 | import com.vividsolutions.jts.geom.LineString; |
||
82 | import com.vividsolutions.jts.geom.Polygon; |
||
83 | import com.vividsolutions.jts.planargraph.Node; |
||
84 | import com.vividsolutions.jts.planargraph.NodeMap; |
||
85 | |||
86 | /**
|
||
87 | * @author fjp Primera prueba acerca de la creaci?n de pol?gonos a partir de una
|
||
88 | * capa de l?neas
|
||
89 | 11089 | jaume | *
|
90 | 8150 | fjp | */
|
91 | public class TopologyExtension extends Extension { |
||
92 | |||
93 | private class MyNode extends Node { |
||
94 | public MyNode(Coordinate pt) {
|
||
95 | super(pt);
|
||
96 | occurrences = 1;
|
||
97 | } |
||
98 | |||
99 | int occurrences;
|
||
100 | |||
101 | public int getOccurrences() { |
||
102 | return occurrences;
|
||
103 | } |
||
104 | |||
105 | public void setOccurrences(int occurrences) { |
||
106 | this.occurrences = occurrences;
|
||
107 | } |
||
108 | |||
109 | } |
||
110 | |||
111 | /**
|
||
112 | * @see com.iver.andami.plugins.IExtension#initialize()
|
||
113 | */
|
||
114 | public void initialize() { |
||
115 | 11089 | jaume | |
116 | 8150 | fjp | } |
117 | |||
118 | /**
|
||
119 | * @see com.iver.andami.plugins.IExtension#execute(java.lang.String)
|
||
120 | */
|
||
121 | public void execute(String s) { |
||
122 | View v = (View) PluginServices.getMDIManager().getActiveWindow(); |
||
123 | MapControl mc = v.getMapControl(); |
||
124 | FLayer[] actives = mc.getMapContext().getLayers().getActives();
|
||
125 | try {
|
||
126 | for (int i = 0; i < actives.length; i++) { |
||
127 | if (actives[i] instanceof FLyrVect) { |
||
128 | FLyrVect lv = (FLyrVect) actives[i]; |
||
129 | if (s.compareTo("CLEAN") == 0) |
||
130 | doClean(lv); |
||
131 | if (s.compareTo("TRIANGULATION") == 0) |
||
132 | doTriangulation(lv); |
||
133 | if (s.compareTo("SHOW_ERRORS") == 0) |
||
134 | doShowNodeErrors(lv); |
||
135 | |||
136 | } |
||
137 | } |
||
138 | } catch (DriverException e) {
|
||
139 | e.printStackTrace(); |
||
140 | NotificationManager.addError(e); |
||
141 | } catch (DriverIOException e) {
|
||
142 | e.printStackTrace(); |
||
143 | NotificationManager.addError(e); |
||
144 | } |
||
145 | |||
146 | } |
||
147 | |||
148 | private void doTriangulation(FLyrVect lv) throws DriverException, |
||
149 | DriverIOException { |
||
150 | View v = (View) PluginServices.getMDIManager().getActiveWindow(); |
||
151 | MapControl mc = v.getMapControl(); |
||
152 | |||
153 | FBitSet bitSet = lv.getRecordset().getSelection(); |
||
154 | Rectangle2D fullExtent = lv.getFullExtent();
|
||
155 | Simplex initialTriangle = new Simplex(new Pnt[] { |
||
156 | new Pnt(fullExtent.getX(), fullExtent.getY()),
|
||
157 | new Pnt(fullExtent.getMaxX(), fullExtent.getY()),
|
||
158 | new Pnt(fullExtent.getCenterX(), fullExtent.getMaxY())});
|
||
159 | |||
160 | DelaunayTriangulation triangulator = new DelaunayTriangulation(initialTriangle);
|
||
161 | |||
162 | for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) { |
||
163 | IGeometry g = lv.getSource().getShape(i); |
||
164 | Geometry jtsG = g.toJTSGeometry(); |
||
165 | Coordinate[] coords = jtsG.getCoordinates();
|
||
166 | if (jtsG.isEmpty())
|
||
167 | continue;
|
||
168 | Coordinate[] linePts = CoordinateArrays
|
||
169 | .removeRepeatedPoints(coords); |
||
170 | Coordinate startPt = linePts[0];
|
||
171 | Coordinate endPt = linePts[linePts.length - 1];
|
||
172 | triangulator.delaunayPlace(startPt); |
||
173 | triangulator.delaunayPlace(endPt); |
||
174 | |||
175 | } |
||
176 | |||
177 | // Ahora recorremos todos los nodos y los que solo hayan sido
|
||
178 | // a?adidos una vez, son dangle o fuzzy.
|
||
179 | // TODO: Poner una tolerancia para que las coordinate cercanas
|
||
180 | // formen un solo nodo.
|
||
181 | GraphicLayer graphicLayer = mc.getMapContext().getGraphicsLayer(); |
||
182 | FSymbol simNodeError = new FSymbol(FShape.POINT, Color.RED); |
||
183 | simNodeError.setSize(10);
|
||
184 | simNodeError.setStyle(FConstant.SYMBOL_STYLE_MARKER_SQUARE); |
||
185 | simNodeError.setFill(null);
|
||
186 | simNodeError.setOutlined(true);
|
||
187 | simNodeError.setOutlineColor(Color.RED);
|
||
188 | |||
189 | int idSymbolPoint = graphicLayer.addSymbol(simNodeError);
|
||
190 | |||
191 | Iterator it = triangulator.iterator();
|
||
192 | |||
193 | while (it.hasNext()) {
|
||
194 | Simplex triangle = (Simplex) it.next(); |
||
195 | for (Iterator otherIt = triangle.facets().iterator(); otherIt |
||
196 | .hasNext();) { |
||
197 | Set facet = (Set) otherIt.next(); |
||
198 | Pnt[] endpoint = (Pnt[]) facet.toArray(new Pnt[2]); |
||
199 | GeneralPathX gp = new GeneralPathX();
|
||
200 | System.err.println(endpoint[0].toString()); |
||
201 | gp.moveTo(endpoint[0].coord(0), endpoint[0].coord(1)); |
||
202 | gp.lineTo(endpoint[1].coord(0), endpoint[1].coord(1)); |
||
203 | IGeometry gAux = ShapeFactory.createPolyline2D(gp); |
||
204 | FGraphic graphic = new FGraphic(gAux, idSymbolPoint);
|
||
205 | graphicLayer.addGraphic(graphic); |
||
206 | } |
||
207 | } |
||
208 | mc.drawGraphics(); |
||
209 | |||
210 | } |
||
211 | |||
212 | /**
|
||
213 | * @param lv
|
||
214 | * FLayerVect de l?neas para convertir a pol?gonos.
|
||
215 | */
|
||
216 | private void doClean(FLyrVect lv) { |
||
217 | TopologyBuilder topologyBuilder = new TopologyBuilder(0, 0); |
||
218 | topologyBuilder.setInputLayer(lv); |
||
219 | |||
220 | View v = (View) PluginServices.getMDIManager().getActiveWindow(); |
||
221 | MapControl mc = v.getMapControl(); |
||
222 | |||
223 | try {
|
||
224 | FBitSet bitSet = lv.getRecordset().getSelection(); |
||
225 | |||
226 | // // First, we need to do "noding"
|
||
227 | // // TODO: This step must be optional
|
||
228 | // ArrayList lineStrings = new ArrayList();
|
||
229 | // for(int i=bitSet.nextSetBit(0); i>=0; i=bitSet.nextSetBit(i+1)) {
|
||
230 | // IGeometry g = lv.getSource().getShape(i);
|
||
231 | // lineStrings.add(g.toJTSGeometry());
|
||
232 | // }
|
||
233 | //
|
||
234 | // Geometry nodedLineStrings = (Geometry) lineStrings.get(0);
|
||
235 | // for (int i = 1; i < lineStrings.size(); i++) {
|
||
236 | // nodedLineStrings =
|
||
237 | // nodedLineStrings.union((Geometry)lineStrings.get(i));
|
||
238 | // }
|
||
239 | 11089 | jaume | //
|
240 | 8150 | fjp | // // FIN noding
|
241 | //
|
||
242 | 11089 | jaume | //
|
243 | 8150 | fjp | // polygonizer.add(nodedLineStrings);
|
244 | |||
245 | Collection polygons = topologyBuilder.buildPolygons();
|
||
246 | Iterator it = polygons.iterator();
|
||
247 | GraphicLayer graphicLayer = mc.getMapContext().getGraphicsLayer(); |
||
248 | int idSymbolPol = graphicLayer
|
||
249 | .addSymbol(new FSymbol(FShape.POLYGON));
|
||
250 | int idSymbolCutEdge = graphicLayer.addSymbol(new FSymbol( |
||
251 | FShape.LINE, Color.BLUE));
|
||
252 | int idSymbolDangle = graphicLayer.addSymbol(new FSymbol( |
||
253 | FShape.LINE, Color.RED));
|
||
254 | while (it.hasNext()) {
|
||
255 | Polygon pol = (Polygon) it.next(); |
||
256 | IGeometry gAux = FConverter.jts_to_igeometry(pol); |
||
257 | FGraphic graphic = new FGraphic(gAux, idSymbolPol);
|
||
258 | graphicLayer.addGraphic(graphic); |
||
259 | } |
||
260 | |||
261 | // LINEAS QUE PARTEN POLIGONOS
|
||
262 | Collection cutEdges = topologyBuilder.getCutEdges();
|
||
263 | it = cutEdges.iterator(); |
||
264 | while (it.hasNext()) {
|
||
265 | LineString lin = (LineString) it.next(); |
||
266 | IGeometry gAux = FConverter.jts_to_igeometry(lin); |
||
267 | FGraphic graphic = new FGraphic(gAux, idSymbolCutEdge);
|
||
268 | graphicLayer.addGraphic(graphic); |
||
269 | } |
||
270 | |||
271 | // LINEAS COLGANTES, QUE NO FORMAN POLIGONO
|
||
272 | Collection dangles = topologyBuilder.getDangles();
|
||
273 | it = dangles.iterator(); |
||
274 | while (it.hasNext()) {
|
||
275 | LineString lin = (LineString) it.next(); |
||
276 | IGeometry gAux = FConverter.jts_to_igeometry(lin); |
||
277 | FGraphic graphic = new FGraphic(gAux, idSymbolDangle);
|
||
278 | graphicLayer.addGraphic(graphic); |
||
279 | } |
||
280 | |||
281 | mc.drawGraphics(); |
||
282 | } catch (DriverException e) {
|
||
283 | e.printStackTrace(); |
||
284 | NotificationManager.addError(e); |
||
285 | } |
||
286 | |||
287 | } |
||
288 | |||
289 | /**
|
||
290 | * We search for origin-endpoints in LineString. Each one will generate a
|
||
291 | * Node. We also fill a map Node-numOccurrences. Dangle and Fuzzy nodes will
|
||
292 | * be those that have an occurrence count = 1. (Node with degree cero in
|
||
293 | * graph's language)
|
||
294 | 11089 | jaume | *
|
295 | 8150 | fjp | * @param lyr
|
296 | * @throws DriverException
|
||
297 | * @throws DriverIOException
|
||
298 | */
|
||
299 | private void doShowNodeErrors(FLyrVect lv) throws DriverException, |
||
300 | DriverIOException { |
||
301 | View v = (View) PluginServices.getMDIManager().getActiveWindow(); |
||
302 | MapControl mc = v.getMapControl(); |
||
303 | |||
304 | // ArrayList nodeErrors = new ArrayList();
|
||
305 | NodeMap nodeMap = new NodeMap();
|
||
306 | FBitSet bitSet = lv.getRecordset().getSelection(); |
||
307 | |||
308 | for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) { |
||
309 | IGeometry g = lv.getSource().getShape(i); |
||
310 | Geometry jtsG = g.toJTSGeometry(); |
||
311 | Coordinate[] coords = jtsG.getCoordinates();
|
||
312 | if (jtsG.isEmpty())
|
||
313 | continue;
|
||
314 | Coordinate[] linePts = CoordinateArrays
|
||
315 | .removeRepeatedPoints(coords); |
||
316 | Coordinate startPt = linePts[0];
|
||
317 | Coordinate endPt = linePts[linePts.length - 1];
|
||
318 | |||
319 | MyNode nStart = (MyNode) nodeMap.find(startPt); |
||
320 | MyNode nEnd = (MyNode) nodeMap.find(endPt); |
||
321 | if (nStart == null) { |
||
322 | nStart = new MyNode(startPt);
|
||
323 | nodeMap.add(nStart); |
||
324 | } else
|
||
325 | nStart.setOccurrences(nStart.getOccurrences() + 1);
|
||
326 | if (nEnd == null) { |
||
327 | nEnd = new MyNode(endPt);
|
||
328 | nodeMap.add(nEnd); |
||
329 | } else
|
||
330 | nEnd.setOccurrences(nEnd.getOccurrences() + 1);
|
||
331 | |||
332 | } |
||
333 | |||
334 | // Ahora recorremos todos los nodos y los que solo hayan sido
|
||
335 | // a?adidos una vez, son dangle o fuzzy.
|
||
336 | // TODO: Poner una tolerancia para que las coordinate cercanas
|
||
337 | // formen un solo nodo.
|
||
338 | GraphicLayer graphicLayer = mc.getMapContext().getGraphicsLayer(); |
||
339 | FSymbol simNodeError = new FSymbol(FShape.POINT, Color.RED); |
||
340 | simNodeError.setSize(10);
|
||
341 | simNodeError.setStyle(FConstant.SYMBOL_STYLE_MARKER_SQUARE); |
||
342 | simNodeError.setFill(null);
|
||
343 | simNodeError.setOutlined(true);
|
||
344 | simNodeError.setOutlineColor(Color.RED);
|
||
345 | |||
346 | int idSymbolPoint = graphicLayer.addSymbol(simNodeError);
|
||
347 | |||
348 | Iterator it = nodeMap.iterator();
|
||
349 | while (it.hasNext()) {
|
||
350 | MyNode node = (MyNode) it.next(); |
||
351 | if (node.getOccurrences() == 1) { |
||
352 | FPoint2D p = FConverter.coordinate2FPoint2D(node |
||
353 | .getCoordinate()); |
||
354 | IGeometry gAux = ShapeFactory.createPoint2D(p); |
||
355 | FGraphic graphic = new FGraphic(gAux, idSymbolPoint);
|
||
356 | graphicLayer.addGraphic(graphic); |
||
357 | |||
358 | } |
||
359 | } |
||
360 | mc.drawGraphics(); |
||
361 | } |
||
362 | |||
363 | /**
|
||
364 | * @see com.iver.andami.plugins.IExtension#isEnabled()
|
||
365 | */
|
||
366 | public boolean isEnabled() { |
||
367 | View v = (View) PluginServices.getMDIManager().getActiveWindow(); |
||
368 | MapControl mc = v.getMapControl(); |
||
369 | if (mc.getMapContext().getLayers().getActives().length > 0) |
||
370 | return true; |
||
371 | return false; |
||
372 | } |
||
373 | |||
374 | /**
|
||
375 | * @see com.iver.andami.plugins.IExtension#isVisible()
|
||
376 | */
|
||
377 | public boolean isVisible() { |
||
378 | 11252 | fjp | // IWindow v = PluginServices.getMDIManager().getActiveWindow();
|
379 | // if (v instanceof View)
|
||
380 | // return true;
|
||
381 | 8150 | fjp | return false; |
382 | } |
||
383 | |||
384 | } |