Statistics
| Revision:

root / trunk / extensions / extCAD / src / com / iver / cit / gvsig / TopologyExtension.java @ 7304

History | View | Annotate | Download (11.9 KB)

1
/* 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;
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
import com.iver.cit.gvsig.topology.TopologyBuilder;
71
import com.iver.cit.gvsig.topology.triangulation.DelaunayTriangulation;
72
import com.iver.cit.gvsig.topology.triangulation.Pnt;
73
import com.iver.cit.gvsig.topology.triangulation.Simplex;
74
import com.vividsolutions.jts.geom.Coordinate;
75
import com.vividsolutions.jts.geom.CoordinateArrays;
76
import com.vividsolutions.jts.geom.Geometry;
77
import com.vividsolutions.jts.geom.LineString;
78
import com.vividsolutions.jts.geom.Polygon;
79
import com.vividsolutions.jts.planargraph.Node;
80
import com.vividsolutions.jts.planargraph.NodeMap;
81

    
82
/**
83
 * @author fjp Primera prueba acerca de la creaci?n de pol?gonos a partir de una
84
 *         capa de l?neas
85
 * 
86
 */
87
public class TopologyExtension extends Extension {
88

    
89
        private class MyNode extends Node {
90
                public MyNode(Coordinate pt) {
91
                        super(pt);
92
                        occurrences = 1;
93
                }
94

    
95
                int occurrences;
96

    
97
                public int getOccurrences() {
98
                        return occurrences;
99
                }
100

    
101
                public void setOccurrences(int occurrences) {
102
                        this.occurrences = occurrences;
103
                }
104

    
105
        }
106

    
107
        /**
108
         * @see com.iver.andami.plugins.IExtension#initialize()
109
         */
110
        public void initialize() {
111
        }
112

    
113
        /**
114
         * @see com.iver.andami.plugins.IExtension#execute(java.lang.String)
115
         */
116
        public void execute(String s) {
117
                View v = (View) PluginServices.getMDIManager().getActiveWindow();
118
                MapControl mc = v.getMapControl();
119
                FLayer[] actives = mc.getMapContext().getLayers().getActives();
120
                try {
121
                        for (int i = 0; i < actives.length; i++) {
122
                                if (actives[i] instanceof FLyrVect) {
123
                                        FLyrVect lv = (FLyrVect) actives[i];
124
                                        if (s.compareTo("CLEAN") == 0)
125
                                                doClean(lv);
126
                                        if (s.compareTo("TRIANGULATION") == 0)
127
                                                doTriangulation(lv);
128
                                        if (s.compareTo("SHOW_ERRORS") == 0)
129
                                                doShowNodeErrors(lv);
130

    
131
                                }
132
                        }
133
                } catch (DriverException e) {
134
                        e.printStackTrace();
135
                        NotificationManager.addError(e);
136
                } catch (DriverIOException e) {
137
                        e.printStackTrace();
138
                        NotificationManager.addError(e);
139
                }
140

    
141
        }
142

    
143
        private void doTriangulation(FLyrVect lv) throws DriverException,
144
                        DriverIOException {
145
                View v = (View) PluginServices.getMDIManager().getActiveWindow();
146
                MapControl mc = v.getMapControl();
147

    
148
                FBitSet bitSet = lv.getRecordset().getSelection();
149
                Rectangle2D fullExtent = lv.getFullExtent();
150
            Simplex initialTriangle = new Simplex(new Pnt[] {
151
                    new Pnt(fullExtent.getX(), fullExtent.getY()),
152
                    new Pnt(fullExtent.getMaxX(), fullExtent.getY()),
153
                    new Pnt(fullExtent.getCenterX(),  fullExtent.getMaxY())});
154

    
155
                DelaunayTriangulation triangulator = new DelaunayTriangulation(initialTriangle);
156

    
157
                for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
158
                        IGeometry g = lv.getSource().getShape(i);
159
                        Geometry jtsG = g.toJTSGeometry();
160
                        Coordinate[] coords = jtsG.getCoordinates();
161
                        if (jtsG.isEmpty())
162
                                continue;
163
                        Coordinate[] linePts = CoordinateArrays
164
                                        .removeRepeatedPoints(coords);
165
                        Coordinate startPt = linePts[0];
166
                        Coordinate endPt = linePts[linePts.length - 1];
167
                        triangulator.delaunayPlace(startPt);
168
                        triangulator.delaunayPlace(endPt);
169

    
170
                }
171

    
172
                // Ahora recorremos todos los nodos y los que solo hayan sido
173
                // a?adidos una vez, son dangle o fuzzy.
174
                // TODO: Poner una tolerancia para que las coordinate cercanas
175
                // formen un solo nodo.
176
                GraphicLayer graphicLayer = mc.getMapContext().getGraphicsLayer();
177
                FSymbol simNodeError = new FSymbol(FShape.POINT, Color.RED);
178
                simNodeError.setSize(10);
179
                simNodeError.setStyle(FConstant.SYMBOL_STYLE_MARKER_SQUARE);
180
                simNodeError.setFill(null);
181
                simNodeError.setOutlined(true);
182
                simNodeError.setOutlineColor(Color.RED);
183

    
184
                int idSymbolPoint = graphicLayer.addSymbol(simNodeError);
185

    
186
                Iterator it = triangulator.iterator();
187

    
188
                while (it.hasNext()) {
189
                        Simplex triangle = (Simplex) it.next();
190
                        for (Iterator otherIt = triangle.facets().iterator(); otherIt
191
                                        .hasNext();) {
192
                                Set facet = (Set) otherIt.next();
193
                                Pnt[] endpoint = (Pnt[]) facet.toArray(new Pnt[2]);
194
                                GeneralPathX gp = new GeneralPathX();
195
                                System.err.println(endpoint[0].toString());
196
                                gp.moveTo(endpoint[0].coord(0), endpoint[0].coord(1));
197
                                gp.lineTo(endpoint[1].coord(0), endpoint[1].coord(1));
198
                                IGeometry gAux = ShapeFactory.createPolyline2D(gp);
199
                                FGraphic graphic = new FGraphic(gAux, idSymbolPoint);
200
                                graphicLayer.addGraphic(graphic);
201
                        }
202
                }
203
                mc.drawGraphics();
204

    
205
        }
206

    
207
        /**
208
         * @param lv
209
         *            FLayerVect de l?neas para convertir a pol?gonos.
210
         */
211
        private void doClean(FLyrVect lv) {
212
                TopologyBuilder topologyBuilder = new TopologyBuilder(0, 0);
213
                topologyBuilder.setInputLayer(lv);
214

    
215
                View v = (View) PluginServices.getMDIManager().getActiveWindow();
216
                MapControl mc = v.getMapControl();
217

    
218
                try {
219
                        FBitSet bitSet = lv.getRecordset().getSelection();
220

    
221
                        // // First, we need to do "noding"
222
                        // // TODO: This step must be optional
223
                        // ArrayList lineStrings = new ArrayList();
224
                        // for(int i=bitSet.nextSetBit(0); i>=0; i=bitSet.nextSetBit(i+1)) {
225
                        // IGeometry g = lv.getSource().getShape(i);
226
                        // lineStrings.add(g.toJTSGeometry());
227
                        // }
228
                        //
229
                        // Geometry nodedLineStrings = (Geometry) lineStrings.get(0);
230
                        // for (int i = 1; i < lineStrings.size(); i++) {
231
                        // nodedLineStrings =
232
                        // nodedLineStrings.union((Geometry)lineStrings.get(i));
233
                        // }
234
                        //                        
235
                        // // FIN noding
236
                        //                        
237
                        //
238
                        // polygonizer.add(nodedLineStrings);
239

    
240
                        Collection polygons = topologyBuilder.buildPolygons();
241
                        Iterator it = polygons.iterator();
242
                        GraphicLayer graphicLayer = mc.getMapContext().getGraphicsLayer();
243
                        int idSymbolPol = graphicLayer
244
                                        .addSymbol(new FSymbol(FShape.POLYGON));
245
                        int idSymbolCutEdge = graphicLayer.addSymbol(new FSymbol(
246
                                        FShape.LINE, Color.BLUE));
247
                        int idSymbolDangle = graphicLayer.addSymbol(new FSymbol(
248
                                        FShape.LINE, Color.RED));
249
                        while (it.hasNext()) {
250
                                Polygon pol = (Polygon) it.next();
251
                                IGeometry gAux = FConverter.jts_to_igeometry(pol);
252
                                FGraphic graphic = new FGraphic(gAux, idSymbolPol);
253
                                graphicLayer.addGraphic(graphic);
254
                        }
255

    
256
                        // LINEAS QUE PARTEN POLIGONOS
257
                        Collection cutEdges = topologyBuilder.getCutEdges();
258
                        it = cutEdges.iterator();
259
                        while (it.hasNext()) {
260
                                LineString lin = (LineString) it.next();
261
                                IGeometry gAux = FConverter.jts_to_igeometry(lin);
262
                                FGraphic graphic = new FGraphic(gAux, idSymbolCutEdge);
263
                                graphicLayer.addGraphic(graphic);
264
                        }
265

    
266
                        // LINEAS COLGANTES, QUE NO FORMAN POLIGONO
267
                        Collection dangles = topologyBuilder.getDangles();
268
                        it = dangles.iterator();
269
                        while (it.hasNext()) {
270
                                LineString lin = (LineString) it.next();
271
                                IGeometry gAux = FConverter.jts_to_igeometry(lin);
272
                                FGraphic graphic = new FGraphic(gAux, idSymbolDangle);
273
                                graphicLayer.addGraphic(graphic);
274
                        }
275

    
276
                        mc.drawGraphics();
277
                } catch (DriverException e) {
278
                        e.printStackTrace();
279
                        NotificationManager.addError(e);
280
                }
281

    
282
        }
283

    
284
        /**
285
         * We search for origin-endpoints in LineString. Each one will generate a
286
         * Node. We also fill a map Node-numOccurrences. Dangle and Fuzzy nodes will
287
         * be those that have an occurrence count = 1. (Node with degree cero in
288
         * graph's language)
289
         * 
290
         * @param lyr
291
         * @throws DriverException
292
         * @throws DriverIOException
293
         */
294
        private void doShowNodeErrors(FLyrVect lv) throws DriverException,
295
                        DriverIOException {
296
                View v = (View) PluginServices.getMDIManager().getActiveWindow();
297
                MapControl mc = v.getMapControl();
298

    
299
                // ArrayList nodeErrors = new ArrayList();
300
                NodeMap nodeMap = new NodeMap();
301
                FBitSet bitSet = lv.getRecordset().getSelection();
302

    
303
                for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
304
                        IGeometry g = lv.getSource().getShape(i);
305
                        Geometry jtsG = g.toJTSGeometry();
306
                        Coordinate[] coords = jtsG.getCoordinates();
307
                        if (jtsG.isEmpty())
308
                                continue;
309
                        Coordinate[] linePts = CoordinateArrays
310
                                        .removeRepeatedPoints(coords);
311
                        Coordinate startPt = linePts[0];
312
                        Coordinate endPt = linePts[linePts.length - 1];
313

    
314
                        MyNode nStart = (MyNode) nodeMap.find(startPt);
315
                        MyNode nEnd = (MyNode) nodeMap.find(endPt);
316
                        if (nStart == null) {
317
                                nStart = new MyNode(startPt);
318
                                nodeMap.add(nStart);
319
                        } else
320
                                nStart.setOccurrences(nStart.getOccurrences() + 1);
321
                        if (nEnd == null) {
322
                                nEnd = new MyNode(endPt);
323
                                nodeMap.add(nEnd);
324
                        } else
325
                                nEnd.setOccurrences(nEnd.getOccurrences() + 1);
326

    
327
                }
328

    
329
                // Ahora recorremos todos los nodos y los que solo hayan sido
330
                // a?adidos una vez, son dangle o fuzzy.
331
                // TODO: Poner una tolerancia para que las coordinate cercanas
332
                // formen un solo nodo.
333
                GraphicLayer graphicLayer = mc.getMapContext().getGraphicsLayer();
334
                FSymbol simNodeError = new FSymbol(FShape.POINT, Color.RED);
335
                simNodeError.setSize(10);
336
                simNodeError.setStyle(FConstant.SYMBOL_STYLE_MARKER_SQUARE);
337
                simNodeError.setFill(null);
338
                simNodeError.setOutlined(true);
339
                simNodeError.setOutlineColor(Color.RED);
340

    
341
                int idSymbolPoint = graphicLayer.addSymbol(simNodeError);
342

    
343
                Iterator it = nodeMap.iterator();
344
                while (it.hasNext()) {
345
                        MyNode node = (MyNode) it.next();
346
                        if (node.getOccurrences() == 1) {
347
                                FPoint2D p = FConverter.coordinate2FPoint2D(node
348
                                                .getCoordinate());
349
                                IGeometry gAux = ShapeFactory.createPoint2D(p);
350
                                FGraphic graphic = new FGraphic(gAux, idSymbolPoint);
351
                                graphicLayer.addGraphic(graphic);
352

    
353
                        }
354
                }
355
                mc.drawGraphics();
356
        }
357

    
358
        /**
359
         * @see com.iver.andami.plugins.IExtension#isEnabled()
360
         */
361
        public boolean isEnabled() {
362
                View v = (View) PluginServices.getMDIManager().getActiveWindow();
363
                MapControl mc = v.getMapControl();
364
                if (mc.getMapContext().getLayers().getActives().length > 0)
365
                        return true;
366
                return false;
367
        }
368

    
369
        /**
370
         * @see com.iver.andami.plugins.IExtension#isVisible()
371
         */
372
        public boolean isVisible() {
373
                IWindow v = PluginServices.getMDIManager().getActiveWindow();
374
                if (v instanceof View)
375
                        return true;
376
                return false;
377
        }
378

    
379
}