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 |
} |