Revision 13591
trunk/libraries/libTopology/src/org/gvsig/jts/RobustLocationIndexedLine.java | ||
---|---|---|
1 |
/* |
|
2 |
* Created on 09-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 |
* Revision 1.1 2007-09-09 11:44:09 azabala |
|
49 |
* Improvements to JTS (robustness problems) |
|
50 |
* |
|
51 |
* |
|
52 |
*/ |
|
53 |
package org.gvsig.jts; |
|
54 |
|
|
55 |
import com.vividsolutions.jts.geom.Coordinate; |
|
56 |
import com.vividsolutions.jts.geom.Geometry; |
|
57 |
import com.vividsolutions.jts.geom.LineSegment; |
|
58 |
import com.vividsolutions.jts.geom.PrecisionModel; |
|
59 |
import com.vividsolutions.jts.linearref.LinearIterator; |
|
60 |
import com.vividsolutions.jts.linearref.LinearLocation; |
|
61 |
import com.vividsolutions.jts.linearref.LocationIndexedLine; |
|
62 |
|
|
63 |
public class RobustLocationIndexedLine extends LocationIndexedLine { |
|
64 |
|
|
65 |
|
|
66 |
private Geometry linearGeom; |
|
67 |
|
|
68 |
|
|
69 |
public RobustLocationIndexedLine(Geometry arg0) { |
|
70 |
super(arg0); |
|
71 |
this.linearGeom = arg0; |
|
72 |
} |
|
73 |
|
|
74 |
public LinearLocation indexOf(Coordinate pt) |
|
75 |
{ |
|
76 |
return indexOfFromStart(pt, null); |
|
77 |
} |
|
78 |
|
|
79 |
// These methods are needed because JTS LocationIndexedLine doesnt have an |
|
80 |
// indexOfAlter |
|
81 |
// method and LocationIndexPoint, which makes all these computations is not |
|
82 |
// a public class |
|
83 |
// report it to JTS project |
|
84 |
|
|
85 |
/* |
|
86 |
* M.Davids has said to me that he has added these methods to JTS (1.9 |
|
87 |
* version). |
|
88 |
* |
|
89 |
* TODO REMOVE THESE METHODS WITH JTS 1.9 |
|
90 |
*/ |
|
91 |
|
|
92 |
public LinearLocation indexOfAfter(LocationIndexedLine indexedLine, |
|
93 |
Coordinate inputPt, |
|
94 |
LinearLocation minIndex) { |
|
95 |
if (minIndex == null) |
|
96 |
return indexedLine.indexOf(inputPt); |
|
97 |
LinearLocation endLoc = LinearLocation.getEndLocation(linearGeom); |
|
98 |
if (endLoc.compareTo(minIndex) <= 0) |
|
99 |
return endLoc; |
|
100 |
|
|
101 |
LinearLocation closestAfter = indexOfFromStart(inputPt, minIndex); |
|
102 |
return closestAfter; |
|
103 |
} |
|
104 |
|
|
105 |
|
|
106 |
|
|
107 |
private LinearLocation indexOfFromStart(Coordinate inputPt, LinearLocation minIndex) |
|
108 |
{ |
|
109 |
double minDistance = Double.MAX_VALUE; |
|
110 |
int minComponentIndex = 0; |
|
111 |
int minSegmentIndex = 0; |
|
112 |
double minFrac = -1.0; |
|
113 |
|
|
114 |
LineSegment seg = new LineSegment(); |
|
115 |
for (LinearIterator it = new LinearIterator(linearGeom); |
|
116 |
it.hasNext(); it.next()) { |
|
117 |
if (! it.isEndOfLine()) { |
|
118 |
seg.p0 = it.getSegmentStart(); |
|
119 |
seg.p1 = it.getSegmentEnd(); |
|
120 |
double segDistance = seg.distance(inputPt); |
|
121 |
|
|
122 |
/* |
|
123 |
* Changes to LocationIndexedLine to avoid robustness problems |
|
124 |
* */ |
|
125 |
PrecisionModel pm = linearGeom.getPrecisionModel(); |
|
126 |
segDistance = pm.makePrecise(segDistance); |
|
127 |
|
|
128 |
double segFrac = segmentFraction(seg, inputPt); |
|
129 |
|
|
130 |
int candidateComponentIndex = it.getComponentIndex(); |
|
131 |
int candidateSegmentIndex = it.getVertexIndex(); |
|
132 |
|
|
133 |
|
|
134 |
if (segDistance < minDistance) { |
|
135 |
// ensure after minLocation, if any |
|
136 |
if (minIndex == null || |
|
137 |
minIndex.compareLocationValues( |
|
138 |
candidateComponentIndex, candidateSegmentIndex, segFrac) |
|
139 |
< 0 |
|
140 |
) { |
|
141 |
// otherwise, save this as new minimum |
|
142 |
minComponentIndex = candidateComponentIndex; |
|
143 |
minSegmentIndex = candidateSegmentIndex; |
|
144 |
minFrac = segFrac; |
|
145 |
minDistance = segDistance; |
|
146 |
} |
|
147 |
} |
|
148 |
} |
|
149 |
} |
|
150 |
LinearLocation loc = new LinearLocation(minComponentIndex, minSegmentIndex, minFrac); |
|
151 |
return loc; |
|
152 |
} |
|
153 |
|
|
154 |
public static double segmentFraction( |
|
155 |
LineSegment seg, |
|
156 |
Coordinate inputPt) |
|
157 |
{ |
|
158 |
double segFrac = seg.projectionFactor(inputPt); |
|
159 |
if (segFrac < 0.0) |
|
160 |
segFrac = 0.0; |
|
161 |
else if (segFrac > 1.0) |
|
162 |
segFrac = 1.0; |
|
163 |
return segFrac; |
|
164 |
} |
|
165 |
|
|
166 |
} |
|
167 |
|
|
0 | 168 |
trunk/libraries/libTopology/src/org/gvsig/jts/GeometrySnapper.java | ||
---|---|---|
10 | 10 |
import com.vividsolutions.jts.geom.Geometry; |
11 | 11 |
import com.vividsolutions.jts.geom.GeometryFactory; |
12 | 12 |
import com.vividsolutions.jts.geom.LineString; |
13 |
import com.vividsolutions.jts.geom.LinearRing; |
|
14 |
import com.vividsolutions.jts.geom.Point; |
|
15 |
import com.vividsolutions.jts.geom.Polygon; |
|
13 | 16 |
|
14 | 17 |
/** |
15 |
* Moves coordinates (in a given tolerance) to force them to coincide with coordinates |
|
18 |
* Moves coordinates of geometries (in a given tolerance) |
|
19 |
* to force them to coincide with coordinates other geometries |
|
16 | 20 |
* in its proximity (the snap tolerance) |
21 |
* |
|
17 | 22 |
*/ |
18 | 23 |
public class GeometrySnapper { |
19 | 24 |
|
... | ... | |
21 | 26 |
|
22 | 27 |
private GeometryFactory geomFactory = new GeometryFactory(); |
23 | 28 |
|
29 |
|
|
24 | 30 |
public GeometrySnapper(double snapTolerance) { |
25 | 31 |
this.snapTolerance = snapTolerance; |
26 | 32 |
} |
... | ... | |
33 | 39 |
Coordinate coordinate; |
34 | 40 |
} |
35 | 41 |
|
36 |
|
|
37 |
public Geometry[] snap(LineString[] geoms){ |
|
42 |
/** |
|
43 |
* Snaps the coordinates of many geometries with the same weight |
|
44 |
* (all coordinates must move) |
|
45 |
* @param geoms |
|
46 |
* @return |
|
47 |
*/ |
|
48 |
public Geometry[] snap(Geometry[] geoms){ |
|
38 | 49 |
int weight[] = new int[geoms.length]; |
39 | 50 |
for(int i = 0; i < geoms.length; i++){ |
40 | 51 |
weight[i] = 1; |
... | ... | |
43 | 54 |
} |
44 | 55 |
|
45 | 56 |
/** |
46 |
* Snaps all the coordinates of the given LineStrings. |
|
57 |
* Snaps all the coordinates of the given geometries |
|
58 |
* . |
|
47 | 59 |
* If many coords are in the same distance tolerance radius, it applies a weighted |
48 |
* average. If one geometry's weight is 0, it will move to the rest coordinates.
|
|
60 |
* average. If one geometry's weight is 0, it wont participate in the average.
|
|
49 | 61 |
* |
50 |
* TODO Generalize LineString to Geometry. It will allow to work with Point, Lines and |
|
51 |
* Polygons (as an outer LineString and many holes). |
|
52 |
* To do that, a geometry will originate a snapped geometry of the same type than |
|
53 |
* the original. |
|
62 |
* @param geoms geometries whose coordinates we want to snap |
|
63 |
* @param weights weight of each geometry in the computation of the weighted average |
|
54 | 64 |
* |
55 | 65 |
* */ |
56 |
public Geometry[] snap(LineString[] geoms, int[] weights) {
|
|
66 |
public Geometry[] snap(Geometry[] geoms, int[] weights) {
|
|
57 | 67 |
SnappingCoordinateMap coordinateMap = new SnappingCoordinateMap(snapTolerance); |
58 |
LineString[] solution = new LineString[geoms.length]; |
|
68 |
|
|
69 |
Geometry[] solution = new Geometry[geoms.length]; |
|
59 | 70 |
for(int i = 0; i < geoms.length; i++){ |
60 | 71 |
Geometry geom = geoms[i]; |
61 | 72 |
Coordinate[] coords = geom.getCoordinates(); |
... | ... | |
97 | 108 |
}//for j |
98 | 109 |
|
99 | 110 |
Coordinate[] newPts = coordList.toCoordinateArray(); |
100 |
solution[i] = geomFactory.createLineString(newPts);
|
|
111 |
solution[i] = createGeometry(newPts, geom);
|
|
101 | 112 |
}//for i |
102 | 113 |
return solution; |
103 | 114 |
} |
104 | 115 |
|
116 |
/** |
|
117 |
* Creates a geometry of the same type as geom with newPts coordinates. |
|
118 |
* geom mustn be a GeometryCollection (MultiPolygon, etc.) |
|
119 |
* @param newPts |
|
120 |
* @param geom |
|
121 |
* @return |
|
122 |
*/ |
|
105 | 123 |
|
124 |
//TODO See how to manage the snap of polygon holes |
|
125 |
|
|
126 |
private Geometry createGeometry(Coordinate[] newPts, Geometry geom) { |
|
127 |
Geometry solution = null; |
|
128 |
if(geom instanceof Point){ |
|
129 |
if(newPts.length == 1) |
|
130 |
return geomFactory.createPoint(newPts[0]); |
|
131 |
else{ |
|
132 |
solution = geomFactory.createMultiPoint(newPts); |
|
133 |
} |
|
134 |
}else if(geom instanceof LineString){ |
|
135 |
solution = geomFactory.createLineString(newPts); |
|
136 |
}else if(geom instanceof Polygon){ |
|
137 |
LinearRing linearRing = geomFactory.createLinearRing(newPts); |
|
138 |
solution = geomFactory.createPolygon(linearRing, null); |
|
139 |
} |
|
140 |
return solution; |
|
141 |
} |
|
142 |
|
|
106 | 143 |
public Coordinate snapAverage(List coordinates, int[] weights){ |
107 | 144 |
List snapList = new ArrayList(); |
108 | 145 |
for(int i = 0; i < coordinates.size(); i++){ |
... | ... | |
176 | 213 |
* @return |
177 | 214 |
*/ |
178 | 215 |
|
179 |
public Coordinate[] snapTo(Coordinate[] srcPts, boolean isClosed, |
|
180 |
Coordinate[] snapPts) { |
|
216 |
private Coordinate[] snapTo(Coordinate[] srcPts, |
|
217 |
boolean isClosed, |
|
218 |
Coordinate[] snapPts) { |
|
181 | 219 |
|
182 | 220 |
CoordinateList coordList = new CoordinateList(srcPts); |
183 | 221 |
int coordinateCount = coordList.size(); |
trunk/libraries/libTopology/src/org/gvsig/jts/LineStringSelfIntersectionChecker.java | ||
---|---|---|
6 | 6 |
|
7 | 7 |
import com.iver.cit.gvsig.util.SnappingCoordinateMap; |
8 | 8 |
import com.vividsolutions.jts.algorithm.RobustLineIntersector; |
9 |
import com.vividsolutions.jts.algorithms.SnapCGAlgorithms; |
|
9 | 10 |
import com.vividsolutions.jts.geom.CoordinateArrays; |
10 | 11 |
import com.vividsolutions.jts.geom.GeometryFactory; |
11 | 12 |
import com.vividsolutions.jts.geom.LineString; |
... | ... | |
86 | 87 |
//TODO Add snap tolerance concept |
87 | 88 |
|
88 | 89 |
public boolean isProper(Coordinate coordinate){ |
89 |
if(lineString instanceof LinearRing) |
|
90 |
if(lineString instanceof LinearRing)//TODO INTRODUCE SNAP
|
|
90 | 91 |
return coordinate.equals2D(lineString.getCoordinateN(0)); |
91 |
else |
|
92 |
return graph.isBoundaryNode(0, coordinate); |
|
92 |
else{ |
|
93 |
boolean solution = graph.isBoundaryNode(0, coordinate); |
|
94 |
if(!solution){ |
|
95 |
//one more try: see the coordinates of the extremes |
|
96 |
//this is needed becase the labeling process for closed linestring |
|
97 |
//dont gives us the desired results |
|
98 |
if(SnapCGAlgorithms.snapEquals2D(coordinate, lineString.getCoordinateN(0), snapTolerance) || |
|
99 |
SnapCGAlgorithms.snapEquals2D(coordinate, lineString.getCoordinateN(lineString.getNumPoints() - 1), snapTolerance)){ |
|
100 |
solution = true; |
|
101 |
}//if |
|
102 |
}//if |
|
103 |
return solution; |
|
104 |
}//else |
|
93 | 105 |
} |
94 | 106 |
|
95 | 107 |
|
trunk/libraries/libTopology/src/org/gvsig/jts/LineStringSplitter.java | ||
---|---|---|
5 | 5 |
import java.util.Collection; |
6 | 6 |
import java.util.Collections; |
7 | 7 |
import java.util.Comparator; |
8 |
import java.util.HashMap; |
|
8 | 9 |
import java.util.Iterator; |
9 | 10 |
import java.util.List; |
10 | 11 |
|
... | ... | |
13 | 14 |
import com.vividsolutions.jts.geom.LineSegment; |
14 | 15 |
import com.vividsolutions.jts.geom.LineString; |
15 | 16 |
import com.vividsolutions.jts.geom.Polygon; |
16 |
import com.vividsolutions.jts.linearref.LengthIndexedLine; |
|
17 | 17 |
import com.vividsolutions.jts.linearref.LinearIterator; |
18 | 18 |
import com.vividsolutions.jts.linearref.LinearLocation; |
19 | 19 |
import com.vividsolutions.jts.linearref.LocationIndexedLine; |
... | ... | |
71 | 71 |
for(int i = 0; i < lineStrings.length; i++){ |
72 | 72 |
LineString geom = lineStrings[i]; |
73 | 73 |
if(GeometrySnapper.isClosed(geom, snapTolerance)){ |
74 |
closedLineStrings.add(lineStrings[i]);
|
|
74 |
closedLineStrings.add(geom);
|
|
75 | 75 |
}else{ |
76 |
unclosedLineStrings.add(lineStrings[i]);
|
|
76 |
unclosedLineStrings.add(geom);
|
|
77 | 77 |
} |
78 | 78 |
} |
79 | 79 |
|
... | ... | |
114 | 114 |
Coordinate[] splitPoints) { |
115 | 115 |
|
116 | 116 |
ArrayList lineStringList = new ArrayList(); |
117 |
LengthIndexedLine lengthLine = new LengthIndexedLine(lineString);
|
|
117 |
RobustLengthIndexedLine lengthLine = new RobustLengthIndexedLine(lineString);
|
|
118 | 118 |
ArrayList nodeIntersections = new ArrayList(); |
119 | 119 |
double linearReferencingIndex = 0d; |
120 | 120 |
for (int i = 0; i < splitPoints.length; i++) { |
... | ... | |
147 | 147 |
|
148 | 148 |
LinearLocation lastLocation = null; |
149 | 149 |
LineIntersection lastIntersection = null; |
150 |
LocationIndexedLine indexedLine = new LocationIndexedLine(lineString);
|
|
150 |
RobustLocationIndexedLine indexedLine = new RobustLocationIndexedLine(lineString);
|
|
151 | 151 |
for (int i = 0; i < nodeIntersections.size(); i++) { |
152 | 152 |
Geometry geometry = null; |
153 | 153 |
LineIntersection li = (LineIntersection) nodeIntersections.get(i); |
154 | 154 |
// LinearLocation location = indexedLine.indexOf(li.coordinate); |
155 |
LinearLocation location = indexOfAfter(indexedLine, lineString,
|
|
155 |
LinearLocation location = indexedLine.indexOfAfter(indexedLine,
|
|
156 | 156 |
li.coordinate, lastLocation); |
157 | 157 |
|
158 | 158 |
if (lastLocation == null) { |
... | ... | |
191 | 191 |
|
192 | 192 |
private static LineString[] splitSimple(LineString lineString, Coordinate[] points) { |
193 | 193 |
LineString[] splittedLS = null; |
194 |
LengthIndexedLine lengthLine = new LengthIndexedLine(lineString); |
|
194 |
RobustLengthIndexedLine lengthLine = new RobustLengthIndexedLine(lineString); |
|
195 |
/* |
|
196 |
* LenghtIndexedLine indexOfAlter method returns the index of a line greater than the specified index. |
|
197 |
* For this reason, we must save in a cache the last computed index for a given coord, and pass |
|
198 |
* this precomputed index to the indexOfAlter method |
|
199 |
* */ |
|
200 |
HashMap coordsIndex = new HashMap(); |
|
195 | 201 |
ArrayList nodeIntersections = new ArrayList(); |
196 |
double linearDistance = 0d; |
|
197 | 202 |
for (int i = 0; i < points.length; i++) { |
198 | 203 |
Coordinate coord = points[i]; |
199 |
double lengthOfNode = lengthLine |
|
200 |
.indexOfAfter(coord, linearDistance); |
|
201 |
linearDistance = lengthOfNode; |
|
202 |
LineIntersection inters = new LineIntersection(); |
|
204 |
Double index = (Double) coordsIndex.get(coord); |
|
205 |
double indexD = 0d; |
|
206 |
if(index != null) |
|
207 |
indexD = index.doubleValue(); |
|
208 |
double computedIndex = lengthLine.indexOfAfter(coord, indexD); |
|
209 |
coordsIndex.put(coord, new Double(computedIndex)); |
|
210 |
LineIntersection inters = new LineIntersection(); |
|
203 | 211 |
inters.coordinate = coord; |
204 |
inters.lenght = lengthOfNode;
|
|
212 |
inters.lenght = computedIndex;
|
|
205 | 213 |
nodeIntersections.add(inters); |
206 | 214 |
}// for |
207 | 215 |
|
... | ... | |
223 | 231 |
|
224 | 232 |
LinearLocation lastLocation = null; |
225 | 233 |
LineIntersection lastIntersection = null; |
226 |
LocationIndexedLine indexedLine = new LocationIndexedLine(lineString);
|
|
234 |
RobustLocationIndexedLine indexedLine = new RobustLocationIndexedLine(lineString);
|
|
227 | 235 |
ArrayList splittedLsList = new ArrayList(); |
228 | 236 |
for (int i = 0; i < nodeIntersections.size(); i++) { |
229 | 237 |
Geometry solution = null; |
230 | 238 |
LineIntersection li = (LineIntersection) nodeIntersections.get(i); |
231 |
LinearLocation location = indexOfAfter(indexedLine, lineString,
|
|
239 |
LinearLocation location = indexedLine.indexOfAfter(indexedLine,
|
|
232 | 240 |
li.coordinate, lastLocation); |
233 | 241 |
if (lastLocation == null) { |
234 | 242 |
LinearLocation from = new LinearLocation(0, 0d); |
... | ... | |
254 | 262 |
|
255 | 263 |
} |
256 | 264 |
|
257 |
/* |
|
258 |
* FIXME: Este algoritmo (duplicar las intersecciones). |
|
259 |
* |
|
260 |
* Probar con: |
|
261 |
* |
|
262 |
* LINESTRING (-16801 780, -19541 2631, -19133 6356, -15839 7702, -14157 |
|
263 |
* 6284, -15503 5972, -15503 6765, -14085 7318, -11969 3929, -16945 1861, |
|
264 |
* -19734 635, -20190 -1143) |
|
265 |
* |
|
266 |
* |
|
267 |
* |
|
268 |
*/ |
|
269 | 265 |
/** |
270 | 266 |
* to propper work, LineStringSplitter needs coordinates to split a line. in |
271 | 267 |
* a self intersected line case, we must to repeat self interesections |
... | ... | |
291 | 287 |
if (splitPoints.length < 1) { |
292 | 288 |
return new LineString[] { lineString }; |
293 | 289 |
} |
290 |
|
|
294 | 291 |
Coordinate[] duplicatedSelfIntersections = duplicateSelfIntersections(splitPoints); |
295 | 292 |
//TODO Create a test case for a linestring not closed for precision reasons |
296 | 293 |
//but closed with a given snap tolerance |
... | ... | |
314 | 311 |
|
315 | 312 |
|
316 | 313 |
|
317 |
// These methods are needed because JTS LocationIndexedLine doesnt have an |
|
318 |
// indexOfAlter |
|
319 |
// method and LocationIndexPoint, which makes all these computations is not |
|
320 |
// a public class |
|
321 |
// report it to JTS project |
|
314 |
|
|
322 | 315 |
|
323 |
/* |
|
324 |
* M.Davids has said to me that he has added these methods to JTS (1.9 |
|
325 |
* version). |
|
326 |
* |
|
327 |
* TODO REMOVE THESE METHODS WITH JTS 1.9 |
|
328 |
*/ |
|
316 |
// private static LinearLocation indexOfFromStart(Coordinate inputPt, |
|
317 |
// LineString linearGeom, LinearLocation minIndex) { |
|
318 |
// double minDistance = Double.MAX_VALUE; |
|
319 |
// int minComponentIndex = 0; |
|
320 |
// int minSegmentIndex = 0; |
|
321 |
// double minFrac = -1.0; |
|
322 |
// |
|
323 |
// LineSegment seg = new LineSegment(); |
|
324 |
// for (LinearIterator it = new LinearIterator(linearGeom); it.hasNext(); it |
|
325 |
// .next()) { |
|
326 |
// if (!it.isEndOfLine()) { |
|
327 |
// seg.p0 = it.getSegmentStart(); |
|
328 |
// seg.p1 = it.getSegmentEnd(); |
|
329 |
// double segDistance = seg.distance(inputPt); |
|
330 |
// double segFrac = segmentFraction(seg, inputPt); |
|
331 |
// |
|
332 |
// int candidateComponentIndex = it.getComponentIndex(); |
|
333 |
// int candidateSegmentIndex = it.getVertexIndex(); |
|
334 |
// if (segDistance < minDistance) { |
|
335 |
// // ensure after minLocation, if any |
|
336 |
// if (minIndex == null |
|
337 |
// || minIndex.compareLocationValues( |
|
338 |
// candidateComponentIndex, |
|
339 |
// candidateSegmentIndex, segFrac) < 0) { |
|
340 |
// // otherwise, save this as new minimum |
|
341 |
// minComponentIndex = candidateComponentIndex; |
|
342 |
// minSegmentIndex = candidateSegmentIndex; |
|
343 |
// minFrac = segFrac; |
|
344 |
// minDistance = segDistance; |
|
345 |
// } |
|
346 |
// } |
|
347 |
// } |
|
348 |
// } |
|
349 |
// LinearLocation loc = new LinearLocation(minComponentIndex, |
|
350 |
// minSegmentIndex, minFrac); |
|
351 |
// return loc; |
|
352 |
// } |
|
329 | 353 |
|
330 |
public static LinearLocation indexOfAfter(LocationIndexedLine indexedLine, |
|
331 |
LineString lineString, Coordinate inputPt, LinearLocation minIndex) { |
|
332 |
if (minIndex == null) |
|
333 |
return indexedLine.indexOf(inputPt); |
|
334 |
LinearLocation endLoc = LinearLocation.getEndLocation(lineString); |
|
335 |
if (endLoc.compareTo(minIndex) <= 0) |
|
336 |
return endLoc; |
|
354 |
// private static double segmentFraction(LineSegment seg, Coordinate inputPt) { |
|
355 |
// double segFrac = seg.projectionFactor(inputPt); |
|
356 |
// if (segFrac < 0.0) |
|
357 |
// segFrac = 0.0; |
|
358 |
// else if (segFrac > 1.0) |
|
359 |
// segFrac = 1.0; |
|
360 |
// return segFrac; |
|
361 |
// } |
|
337 | 362 |
|
338 |
LinearLocation closestAfter = indexOfFromStart(inputPt, lineString, |
|
339 |
minIndex); |
|
340 |
return closestAfter; |
|
341 |
} |
|
342 |
|
|
343 |
private static LinearLocation indexOfFromStart(Coordinate inputPt, |
|
344 |
LineString linearGeom, LinearLocation minIndex) { |
|
345 |
double minDistance = Double.MAX_VALUE; |
|
346 |
int minComponentIndex = 0; |
|
347 |
int minSegmentIndex = 0; |
|
348 |
double minFrac = -1.0; |
|
349 |
|
|
350 |
LineSegment seg = new LineSegment(); |
|
351 |
for (LinearIterator it = new LinearIterator(linearGeom); it.hasNext(); it |
|
352 |
.next()) { |
|
353 |
if (!it.isEndOfLine()) { |
|
354 |
seg.p0 = it.getSegmentStart(); |
|
355 |
seg.p1 = it.getSegmentEnd(); |
|
356 |
double segDistance = seg.distance(inputPt); |
|
357 |
double segFrac = segmentFraction(seg, inputPt); |
|
358 |
|
|
359 |
int candidateComponentIndex = it.getComponentIndex(); |
|
360 |
int candidateSegmentIndex = it.getVertexIndex(); |
|
361 |
if (segDistance < minDistance) { |
|
362 |
// ensure after minLocation, if any |
|
363 |
if (minIndex == null |
|
364 |
|| minIndex.compareLocationValues( |
|
365 |
candidateComponentIndex, |
|
366 |
candidateSegmentIndex, segFrac) < 0) { |
|
367 |
// otherwise, save this as new minimum |
|
368 |
minComponentIndex = candidateComponentIndex; |
|
369 |
minSegmentIndex = candidateSegmentIndex; |
|
370 |
minFrac = segFrac; |
|
371 |
minDistance = segDistance; |
|
372 |
} |
|
373 |
} |
|
374 |
} |
|
375 |
} |
|
376 |
LinearLocation loc = new LinearLocation(minComponentIndex, |
|
377 |
minSegmentIndex, minFrac); |
|
378 |
return loc; |
|
379 |
} |
|
380 |
|
|
381 |
private static double segmentFraction(LineSegment seg, Coordinate inputPt) { |
|
382 |
double segFrac = seg.projectionFactor(inputPt); |
|
383 |
if (segFrac < 0.0) |
|
384 |
segFrac = 0.0; |
|
385 |
else if (segFrac > 1.0) |
|
386 |
segFrac = 1.0; |
|
387 |
return segFrac; |
|
388 |
} |
|
389 |
|
|
390 | 363 |
} |
trunk/libraries/libTopology/src/org/gvsig/jts/GeometryCracker.java | ||
---|---|---|
44 | 44 |
/* |
45 | 45 |
* This code is extracted from the class LineStringSnapper of JTS |
46 | 46 |
* */ |
47 |
public Coordinate[] crackTo(Coordinate[] srcPts, Coordinate[] snapPts) {
|
|
47 |
private Coordinate[] crackTo(Coordinate[] srcPts, Coordinate[] snapPts) {
|
|
48 | 48 |
CoordinateList coordList = new CoordinateList(srcPts); |
49 | 49 |
crackSegments(coordList, snapPts); |
50 | 50 |
Coordinate[] newPts = coordList.toCoordinateArray(); |
trunk/libraries/libTopology/src/org/gvsig/jts/RobustLengthIndexedLine.java | ||
---|---|---|
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 |
* Revision 1.1 2007-09-09 11:44:09 azabala |
|
49 |
* Improvements to JTS (robustness problems) |
|
50 |
* |
|
51 |
* |
|
52 |
*/ |
|
53 |
package org.gvsig.jts; |
|
54 |
|
|
55 |
import com.vividsolutions.jts.geom.Coordinate; |
|
56 |
import com.vividsolutions.jts.geom.Geometry; |
|
57 |
import com.vividsolutions.jts.geom.LineSegment; |
|
58 |
import com.vividsolutions.jts.geom.PrecisionModel; |
|
59 |
import com.vividsolutions.jts.linearref.LengthIndexedLine; |
|
60 |
import com.vividsolutions.jts.linearref.LinearIterator; |
|
61 |
|
|
62 |
/** |
|
63 |
* Implementation of LengthIndexedLine to avoid robustness problems. |
|
64 |
* |
|
65 |
* TODO If JTS official implementation of LenghtIndexedLine solve the problem |
|
66 |
* that has been already reported about precission robustness, DELETE THIS CLASS |
|
67 |
* |
|
68 |
* @author azabala |
|
69 |
* |
|
70 |
*/ |
|
71 |
public class RobustLengthIndexedLine extends LengthIndexedLine { |
|
72 |
|
|
73 |
/** |
|
74 |
* Superclass has no methods to expose linearGeom, and is private, so we |
|
75 |
* need to mantain a reference here |
|
76 |
*/ |
|
77 |
private Geometry linearGeom; |
|
78 |
|
|
79 |
public RobustLengthIndexedLine(Geometry arg0) { |
|
80 |
super(arg0); |
|
81 |
this.linearGeom = arg0; |
|
82 |
|
|
83 |
} |
|
84 |
|
|
85 |
public double indexOf(Coordinate pt) { |
|
86 |
return indexOfFromStart(pt, -1); |
|
87 |
} |
|
88 |
|
|
89 |
public double indexOfAfter(Coordinate pt, double minIndex) { |
|
90 |
if (minIndex < 0.0) |
|
91 |
return indexOf(pt); |
|
92 |
double endIndex = linearGeom.getLength(); |
|
93 |
if (endIndex < minIndex) |
|
94 |
return endIndex; |
|
95 |
double closestAfter = indexOfFromStart(pt, minIndex); |
|
96 |
return closestAfter; |
|
97 |
} |
|
98 |
|
|
99 |
/** |
|
100 |
* Return the first index ocurrence of the given coordinate grater than |
|
101 |
* minIndex. |
|
102 |
*/ |
|
103 |
|
|
104 |
private double indexOfFromStart(Coordinate inputPt, double minIndex) { |
|
105 |
double minDistance = Double.MAX_VALUE; |
|
106 |
double ptMeasure = minIndex; |
|
107 |
double segmentStartMeasure = 0.0; |
|
108 |
LineSegment seg = new LineSegment(); |
|
109 |
LinearIterator it = new LinearIterator(linearGeom); |
|
110 |
while (it.hasNext()) { |
|
111 |
if (!it.isEndOfLine()) { |
|
112 |
seg.p0 = it.getSegmentStart(); |
|
113 |
seg.p1 = it.getSegmentEnd(); |
|
114 |
double segDistance = seg.distance(inputPt); |
|
115 |
/* |
|
116 |
* these two lines of code are the only novelties respect to LenghtIndexedLine |
|
117 |
*/ |
|
118 |
PrecisionModel pm = linearGeom.getPrecisionModel(); |
|
119 |
segDistance = pm.makePrecise(segDistance); |
|
120 |
/* |
|
121 |
* FIXME Remove them if JTS solve the problem |
|
122 |
*/ |
|
123 |
double segMeasureToPt = segmentNearestMeasure(seg, inputPt, |
|
124 |
segmentStartMeasure); |
|
125 |
|
|
126 |
if (segDistance < minDistance && segMeasureToPt > minIndex) { |
|
127 |
ptMeasure = segMeasureToPt; |
|
128 |
minDistance = segDistance; |
|
129 |
} |
|
130 |
segmentStartMeasure += seg.getLength(); |
|
131 |
} |
|
132 |
it.next(); |
|
133 |
} |
|
134 |
return ptMeasure; |
|
135 |
} |
|
136 |
|
|
137 |
private double segmentNearestMeasure(LineSegment seg, Coordinate inputPt, |
|
138 |
double segmentStartMeasure) { |
|
139 |
// found new minimum, so compute location distance of point |
|
140 |
double projFactor = seg.projectionFactor(inputPt); |
|
141 |
if (projFactor <= 0.0) |
|
142 |
return segmentStartMeasure; |
|
143 |
if (projFactor <= 1.0) |
|
144 |
return segmentStartMeasure + projFactor * seg.getLength(); |
|
145 |
// projFactor > 1.0 |
|
146 |
return segmentStartMeasure + seg.getLength(); |
|
147 |
} |
|
148 |
|
|
149 |
} |
|
0 | 150 |
Also available in: Unified diff