Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libTopology / src / org / gvsig / jts / LineStringSelfIntersectionChecker.java @ 19632

History | View | Annotate | Download (8.49 KB)

1
/*
2
 * Created on 07-sep-2007
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
/* CVS MESSAGES:
45
 *
46
 * $Id: 
47
 * $Log: 
48
 */
49
package org.gvsig.jts;
50

    
51
import java.util.ArrayList;
52
import java.util.Iterator;
53
import java.util.List;
54

    
55
import com.iver.cit.gvsig.util.SnappingCoordinateMap;
56
import com.vividsolutions.jts.algorithm.RobustLineIntersector;
57
import com.vividsolutions.jts.algorithms.SnapCGAlgorithms;
58
import com.vividsolutions.jts.geom.Coordinate;
59
import com.vividsolutions.jts.geom.Geometry;
60
import com.vividsolutions.jts.geom.LineString;
61
import com.vividsolutions.jts.geom.LinearRing;
62
import com.vividsolutions.jts.geomgraph.Edge;
63
import com.vividsolutions.jts.geomgraph.EdgeIntersection;
64
import com.vividsolutions.jts.geomgraph.EdgeIntersectionList;
65
import com.vividsolutions.jts.geomgraph.GeometryGraph;
66
import com.vividsolutions.jts.geomgraph.index.EdgeSetIntersector;
67
import com.vividsolutions.jts.geomgraph.index.SegmentIntersector;
68
import com.vividsolutions.jts.geomgraph.index.SimpleMCSweepLineIntersector;
69

    
70
/**
71
 * 
72
 * Cheks if a given linestring has selfintersections, and gives methods to split
73
 * a line with self intersections in many lines.
74
 * 
75
 * Doesnt consideer snap tolerance.
76
 * 
77
 * @author azabala
78
 * 
79
 */
80
public class LineStringSelfIntersectionChecker {
81

    
82
        public final static double DEFAULT_SNAP_TOLERANCE = 0d;
83

    
84
        protected LineString lineString;
85

    
86
        protected GeometryGraph graph;
87

    
88

    
89
        protected boolean hasInitialized = false;
90

    
91
        protected Coordinate[] selfIntersections;
92

    
93
        protected double snapTolerance;
94

    
95
        
96
        
97
        public LineStringSelfIntersectionChecker(LineString lineString,
98
                        double snapTolerance) {
99
                this.lineString = lineString;
100
                this.snapTolerance = snapTolerance;
101
                this.graph = new GeometryGraph(0, lineString);
102
        }
103

    
104
        
105
        public LineStringSelfIntersectionChecker(LineString lineString) {
106
                this(lineString, DEFAULT_SNAP_TOLERANCE);
107
        }
108

    
109
        public boolean hasSelfIntersections() {
110
                if (!hasInitialized) {
111
                        initialize();
112
                        hasInitialized = true;
113
                }// if
114
                if (selfIntersections != null && selfIntersections.length > 0)
115
                        return true;
116
                else
117
                        return false;
118
        }
119

    
120
        /**
121
         * Receives a coordinate of the geometry, and returns if it could be
122
         * consideered part of the graph (proper).
123
         * 
124
         * In linestrings, end points are proper (must not be consideered self
125
         * intersection)
126
         * 
127
         * In linearrings, anything is boundary
128
         * 
129
         * @param coordinate
130
         * @return
131
         */
132
        public boolean isProper(Coordinate coordinate) {
133
                if (lineString instanceof LinearRing){
134
//                        return coordinate.equals2D(lineString.getCoordinateN(0));
135
                        //in a LinearRing first and last point must be equals
136
                        return SnapCGAlgorithms.snapEquals2D(coordinate, lineString
137
                                        .getCoordinateN(0), snapTolerance);
138
                        
139
                }
140
                
141
                
142
                
143
                
144
                
145
                
146
                
147
                
148
                else {
149
                        boolean solution = false;
150
//                        boolean solution = graph.isBoundaryNode(0, coordinate);
151
//                        if (!solution) {
152
                                // one more try: see the coordinates of the extremes
153
                                // this is needed becase the labeling process for closed
154
                                // linestring
155
                                // dont gives us the desired results
156
                                if (SnapCGAlgorithms.snapEquals2D(coordinate, lineString.getCoordinateN(0), snapTolerance) || 
157
                                        SnapCGAlgorithms.snapEquals2D(coordinate, lineString.getCoordinateN(lineString.getNumPoints() - 1), snapTolerance)) 
158
                                {
159
                                        //the coordinate is equal to one of the nodes of a lineString
160
                                        //if the lineString is not closed, it could not be proper
161
                                        if(JtsUtil.isClosed(lineString, snapTolerance))
162
                                                solution = true;
163
                                }// if
164
//                        }// if
165
                        return solution;
166
                }// else
167
        }
168

    
169
        // TODO Add snap tolerance concept
170
        // trick extracted from JTS examples
171
        // TODO REVISAR CUAL ES MEJOR, initialize o initialize2
172
//        private void initialize2() {
173
//                List endPtList = new ArrayList();
174
//                endPtList.add(lineString.getCoordinateN(0));
175
//                endPtList.add(lineString.getCoordinateN(lineString.getNumPoints() - 1));
176
//                Coordinate[] endPts = CoordinateArrays.toCoordinateArray(endPtList);
177
//                Geometry lineStringNodes = new GeometryFactory()
178
//                                .createMultiPoint(endPts);
179
//                Geometry nodedLine = lineString.union(lineStringNodes);
180
//                List endPtList2 = new ArrayList();
181
//                endPtList2.add(((LineString) nodedLine).getCoordinateN(0));
182
//                endPtList2.add(((LineString) nodedLine).getCoordinateN(lineString
183
//                                .getNumPoints() - 1));
184
//                Coordinate[] endPts2 = CoordinateArrays.toCoordinateArray(endPtList2);
185
//                Geometry lineStringNodes2 = new GeometryFactory()
186
//                                .createMultiPoint(endPts2);
187
//                Geometry selfs = lineStringNodes.difference(lineStringNodes2);
188
//                selfIntersections = selfs.getCoordinates();
189
//        }
190

    
191
        // TODO Add snap tolerance concept
192
        // this algorithm has been designed by us
193
        protected void initialize() {
194
                ArrayList<Coordinate> selfIntersectionsList = new ArrayList<Coordinate>();
195
                SnappingCoordinateMap selfIntersectionsMap = new SnappingCoordinateMap(
196
                                snapTolerance);
197
                List edges = computeSelfNodes();
198
//                List edges = computeSelfNodesWithSnap();
199
                Iterator i = edges.iterator();
200
                while (i.hasNext()) {// for each edge graph
201
                        Edge e = (Edge) i.next();
202
                        EdgeIntersectionList eiList = e.getEdgeIntersectionList();
203
                        for (Iterator eiIt = eiList.iterator(); eiIt.hasNext();) {
204
                                EdgeIntersection ei = (EdgeIntersection) eiIt.next();
205
                                if (!isProper(ei.coord)) {
206
                                        if (!selfIntersectionsMap.containsKey(ei.coord)) {
207
                                                selfIntersectionsList.add(ei.coord);
208
                                                selfIntersectionsMap.put(ei.coord, ei.coord);
209
                                        }//if
210
                                }//if
211
                        }// for
212
                }// while
213
                int numSelfIntersections = selfIntersectionsList.size();
214
                if (numSelfIntersections > 0) {
215
                        selfIntersections = new Coordinate[numSelfIntersections];
216
                        selfIntersectionsList.toArray(selfIntersections);
217
                }
218
        }
219

    
220
        /**
221
         * This method is needed, instead graph.computeSelfNodes because when a
222
         * geometry is of type linestring, the call to
223
         * esi.computeIntersections(edges, si, param) always pass param = false
224
         * (self intersections ara allowed for linestrings in OGC SFS geometry
225
         * model)
226
         * 
227
         * We need param=true
228
         * 
229
         */
230

    
231
        // TODO Add snap tolerance concept
232
        private List computeSelfNodes() {
233
                SegmentIntersector si = new SegmentIntersector(
234
                                new RobustLineIntersector(), true, false);
235
                EdgeSetIntersector esi = new SimpleMCSweepLineIntersector();
236
                List edges = new ArrayList();
237
                Iterator edgesIt = graph.getEdgeIterator();
238
                while (edgesIt.hasNext()) {
239
                        edges.add(edgesIt.next());
240
                }
241
                esi.computeIntersections(edges, si, true);
242
                return edges;
243
        }
244
        
245
        
246
//        private List computeSelfNodesWithSnap() {
247
//                LineIntersector li = new SnapLineIntersector(snapTolerance);
248
//                SegmentIntersector si = new SegmentIntersector(li, true, false);
249
//                SnapSimpleMCSweepLineIntersector esi = new SnapSimpleMCSweepLineIntersector();
250
//                List edges = new ArrayList();
251
//                Iterator edgesIt = graph.getEdgeIterator();
252
//                while (edgesIt.hasNext()) {
253
//                        edges.add(edgesIt.next());
254
//                }
255
//                esi.computeIntersections(edges, si, true);
256
//                return edges;
257
//        }
258
        
259

    
260
        /**
261
         * Returns the self intersections of the linestring
262
         */
263
        public Coordinate[] getSelfIntersections() {
264
                return selfIntersections;
265
        }
266

    
267
        public Geometry[] clean() {
268
                if (!hasInitialized) {
269
                        initialize();
270
                        hasInitialized = true;
271
                }// if
272
                if (selfIntersections == null && selfIntersections.length < 1)
273
                        return new Geometry[] { lineString };
274
                else
275
                        return LineStringSplitter.removeSelfIntersections(lineString,
276
                                        selfIntersections, snapTolerance);
277
        }
278

    
279
        public LineString getLineString() {
280
                return lineString;
281
        }
282

    
283
        public void setLineString(LineString lineString) {
284
                this.lineString = lineString;
285
        }
286

    
287
}