Revision 19632
trunk/libraries/libTopology/src/org/gvsig/jts/JtsUtil.java | ||
---|---|---|
74 | 74 |
import com.vividsolutions.jts.geom.GeometryFactory; |
75 | 75 |
import com.vividsolutions.jts.geom.LineString; |
76 | 76 |
import com.vividsolutions.jts.geom.LinearRing; |
77 |
import com.vividsolutions.jts.geom.MultiLineString; |
|
77 | 78 |
import com.vividsolutions.jts.geom.MultiPoint; |
78 | 79 |
import com.vividsolutions.jts.geom.MultiPolygon; |
79 | 80 |
import com.vividsolutions.jts.geom.Point; |
80 | 81 |
import com.vividsolutions.jts.geom.Polygon; |
82 |
import com.vividsolutions.jts.geom.PrecisionModel; |
|
81 | 83 |
import com.vividsolutions.jts.geomgraph.Edge; |
82 | 84 |
import com.vividsolutions.jts.geomgraph.EdgeIntersectionList; |
83 | 85 |
import com.vividsolutions.jts.geomgraph.GeometryGraph; |
... | ... | |
89 | 91 |
* |
90 | 92 |
*/ |
91 | 93 |
public class JtsUtil { |
92 |
public static GeometryFactory geomFactory = new GeometryFactory(); |
|
94 |
//FIXME PrecionModel's scale should be configurable by a JTS preferences |
|
95 |
//dialog |
|
96 |
public static final PrecisionModel GVSIG_PRECISION_MODEL = |
|
97 |
new PrecisionModel(10000); |
|
98 |
|
|
99 |
public static final GeometryFactory GEOMETRY_FACTORY = |
|
100 |
new GeometryFactory(GVSIG_PRECISION_MODEL); |
|
93 | 101 |
|
94 | 102 |
public static Geometry createGeometry(Coordinate[] coords, |
95 | 103 |
String geometryType) { |
96 | 104 |
if (geometryType.equalsIgnoreCase("POINT")) { |
97 |
return geomFactory.createPoint(coords[0]);
|
|
105 |
return GEOMETRY_FACTORY.createPoint(coords[0]);
|
|
98 | 106 |
} else if (geometryType.equalsIgnoreCase("LINESTRING")) { |
99 |
return geomFactory.createLineString(coords);
|
|
107 |
return GEOMETRY_FACTORY.createLineString(coords);
|
|
100 | 108 |
} else if (geometryType.equalsIgnoreCase("LINEARRING")) { |
101 |
return geomFactory.createLinearRing(coords);
|
|
109 |
return GEOMETRY_FACTORY.createLinearRing(coords);
|
|
102 | 110 |
} |
103 | 111 |
// else if (geometryType.equalsIgnoreCase("POLYGON")) { |
104 | 112 |
// // LinearRing exterior = geomFactory.createLinearRing(coords); |
105 | 113 |
// // return geomFactory.createPolygon(exterior, null); |
106 | 114 |
// } |
107 | 115 |
else if (geometryType.equalsIgnoreCase("MULTIPOINT")) { |
108 |
return geomFactory.createMultiPoint(coords);
|
|
116 |
return GEOMETRY_FACTORY.createMultiPoint(coords);
|
|
109 | 117 |
} |
110 | 118 |
return null; |
111 | 119 |
} |
... | ... | |
123 | 131 |
- firstPointOfShell + 1]; |
124 | 132 |
System.arraycopy(coords, firstPointOfShell, shellCoords, 0, |
125 | 133 |
shellCoords.length); |
126 |
LinearRing shell = geomFactory.createLinearRing(shellCoords);
|
|
134 |
LinearRing shell = GEOMETRY_FACTORY.createLinearRing(shellCoords);
|
|
127 | 135 |
|
128 | 136 |
LinearRing[] holes = null; |
129 | 137 |
if (numberOfHoles > 0) { |
... | ... | |
137 | 145 |
+ 1]; |
138 | 146 |
System.arraycopy(coords, firstPointOfHole, holeCoords, 0, |
139 | 147 |
holeCoords.length); |
140 |
holes[i - 1] = geomFactory.createLinearRing(holeCoords);
|
|
148 |
holes[i - 1] = GEOMETRY_FACTORY.createLinearRing(holeCoords);
|
|
141 | 149 |
} |
142 | 150 |
firstPointOfHole = indexOfParts[indexOfParts.length - 1]; |
143 | 151 |
lastPointOfHole = coords.length - 1; |
144 | 152 |
holeCoords = new Coordinate[lastPointOfHole - firstPointOfHole + 1]; |
145 | 153 |
System.arraycopy(coords, firstPointOfHole, holeCoords, 0, |
146 | 154 |
holeCoords.length); |
147 |
holes[holes.length - 1] = geomFactory.createLinearRing(holeCoords);
|
|
155 |
holes[holes.length - 1] = GEOMETRY_FACTORY.createLinearRing(holeCoords);
|
|
148 | 156 |
} |
149 |
return geomFactory.createPolygon(shell, holes);
|
|
157 |
return GEOMETRY_FACTORY.createPolygon(shell, holes);
|
|
150 | 158 |
} |
151 | 159 |
|
152 | 160 |
/** |
... | ... | |
174 | 182 |
} |
175 | 183 |
return indexOfParts; |
176 | 184 |
} |
185 |
|
|
186 |
public static MultiLineString convertToMultiLineString(GeometryCollection geomCol){ |
|
187 |
List<LineString> lines = new ArrayList<LineString>(); |
|
188 |
int numGeometries = geomCol.getNumGeometries(); |
|
189 |
for (int i = 0; i < numGeometries; i++) { |
|
190 |
Geometry geom = geomCol.getGeometryN(i); |
|
191 |
if (geom instanceof LineString) |
|
192 |
lines.add((LineString) geom); |
|
193 |
else if (geom instanceof MultiLineString) { |
|
194 |
MultiLineString multiLine = (MultiLineString) geom; |
|
195 |
int numLines = multiLine.getNumGeometries(); |
|
196 |
for (int j = 0; j < numLines; j++) { |
|
197 |
lines.add((LineString) multiLine.getGeometryN(j)); |
|
198 |
}// j |
|
199 |
}// else |
|
200 |
else if (geom instanceof GeometryCollection) { |
|
201 |
MultiLineString multiLine = convertToMultiLineString((GeometryCollection) geom); |
|
202 |
int numLines = multiLine.getNumGeometries(); |
|
203 |
for (int j = 0; j < numLines; j++) { |
|
204 |
lines.add((LineString) multiLine.getGeometryN(j)); |
|
205 |
}// j |
|
206 |
}// else |
|
207 |
}// for i |
|
208 |
LineString[] lineArray = new LineString[lines.size()]; |
|
209 |
lines.toArray(lineArray); |
|
210 |
return GEOMETRY_FACTORY.createMultiLineString(lineArray); |
|
211 |
} |
|
212 |
|
|
213 |
|
|
177 | 214 |
|
178 |
public static MultiPolygon convertIfPossible(GeometryCollection geomCol) {
|
|
215 |
public static MultiPolygon convertToMultiPolygon(GeometryCollection geomCol) {
|
|
179 | 216 |
List<Polygon> polygons = new ArrayList<Polygon>(); |
180 | 217 |
int numGeometries = geomCol.getNumGeometries(); |
181 | 218 |
for (int i = 0; i < numGeometries; i++) { |
... | ... | |
190 | 227 |
}// j |
191 | 228 |
}// else |
192 | 229 |
else if (geom instanceof GeometryCollection) { |
193 |
MultiPolygon multiPol = convertIfPossible((GeometryCollection) geom);
|
|
230 |
MultiPolygon multiPol = convertToMultiPolygon((GeometryCollection) geom);
|
|
194 | 231 |
int numPols = multiPol.getNumGeometries(); |
195 | 232 |
for (int j = 0; j < numPols; j++) { |
196 | 233 |
polygons.add((Polygon) multiPol.getGeometryN(j)); |
... | ... | |
199 | 236 |
}// for i |
200 | 237 |
Polygon[] polyArray = new Polygon[polygons.size()]; |
201 | 238 |
polygons.toArray(polyArray); |
202 |
return new GeometryFactory().createMultiPolygon(polyArray);
|
|
239 |
return GEOMETRY_FACTORY.createMultiPolygon(polyArray);
|
|
203 | 240 |
} |
204 | 241 |
|
205 | 242 |
public static boolean isClosed(Geometry geom) { |
... | ... | |
222 | 259 |
|
223 | 260 |
Geometry[] solutionG = GeometryFactory |
224 | 261 |
.toGeometryArray(solutionGeoms); |
225 |
solution = geomFactory.createGeometryCollection(solutionG);
|
|
262 |
solution = GEOMETRY_FACTORY.createGeometryCollection(solutionG);
|
|
226 | 263 |
return solution; |
227 | 264 |
} else if (geom instanceof LineString) { |
228 | 265 |
LineString solution = null; |
... | ... | |
232 | 269 |
.getCoordinateN(tempGeom.getNumPoints() - 1); |
233 | 270 |
if (!SnapCGAlgorithms.snapEquals2D(start, end, snapTolerance)) { |
234 | 271 |
Coordinate[] coordinates = { start, end }; |
235 |
solution = geomFactory.createLineString(coordinates);
|
|
272 |
solution = GEOMETRY_FACTORY.createLineString(coordinates);
|
|
236 | 273 |
} |
237 | 274 |
return solution; |
238 | 275 |
|
... | ... | |
255 | 292 |
Geometry[] solutionArray = GeometryFactory |
256 | 293 |
.toGeometryArray(solutionGeoms); |
257 | 294 |
if (solutionArray.length > 0) |
258 |
solution = geomFactory.createGeometryCollection(solutionArray);
|
|
295 |
solution = GEOMETRY_FACTORY.createGeometryCollection(solutionArray);
|
|
259 | 296 |
return solution; |
260 | 297 |
}// else |
261 | 298 |
|
... | ... | |
352 | 389 |
public static LinearRing reverse(LinearRing ring) { |
353 | 390 |
CoordinateSequence seq = ring.getCoordinateSequence(); |
354 | 391 |
CoordinateSequences.reverse(seq); |
355 |
LinearRing solution = geomFactory.createLinearRing(seq);
|
|
392 |
LinearRing solution = GEOMETRY_FACTORY.createLinearRing(seq);
|
|
356 | 393 |
return solution; |
357 | 394 |
} |
358 | 395 |
|
... | ... | |
368 | 405 |
for (int i = 0; i < geometries.length; i++) { |
369 | 406 |
theGeoms[i] = ((IGeometry) geometries[i]).toJTSGeometry(); |
370 | 407 |
} |
371 |
solution = geomFactory.createGeometryCollection(theGeoms);
|
|
408 |
solution = GEOMETRY_FACTORY.createGeometryCollection(theGeoms);
|
|
372 | 409 |
|
373 | 410 |
} else if (fmapGeometry instanceof FMultiPoint2D) { |
374 | 411 |
solution = ((FMultiPoint2D) fmapGeometry).toJTSGeometry(); |
trunk/libraries/libTopology/src/org/gvsig/jts/GeometrySnapper.java | ||
---|---|---|
324 | 324 |
for(int i = 0; i < numGeometries; i++){ |
325 | 325 |
lineStrings[i] = (LineString) snap(multiLine.getGeometryN(i)); |
326 | 326 |
} |
327 |
return JtsUtil.geomFactory.createMultiLineString(lineStrings);
|
|
327 |
return JtsUtil.GEOMETRY_FACTORY.createMultiLineString(lineStrings);
|
|
328 | 328 |
|
329 | 329 |
}else if(geom.getGeometryType().equalsIgnoreCase("MultiPolygon")){ |
330 | 330 |
MultiPolygon multiPolygon = (MultiPolygon) geom; |
... | ... | |
333 | 333 |
for(int i = 0; i < numGeometries; i++){ |
334 | 334 |
polygons[i] = (Polygon) snap(multiPolygon.getGeometryN(i)); |
335 | 335 |
} |
336 |
return JtsUtil.geomFactory.createMultiPolygon(polygons);
|
|
336 |
return JtsUtil.GEOMETRY_FACTORY.createMultiPolygon(polygons);
|
|
337 | 337 |
|
338 | 338 |
|
339 | 339 |
}else if(geom.getGeometryType().equalsIgnoreCase("GeometryCollection")){ |
... | ... | |
343 | 343 |
for(int i = 0; i < numGeometries; i++){ |
344 | 344 |
geoms[i] = snap(geomCol.getGeometryN(i)); |
345 | 345 |
} |
346 |
return JtsUtil.geomFactory.createGeometryCollection(geoms);
|
|
346 |
return JtsUtil.GEOMETRY_FACTORY.createGeometryCollection(geoms);
|
|
347 | 347 |
}else if(geom.getGeometryType().equalsIgnoreCase("LineString") || |
348 | 348 |
geom.getGeometryType().equalsIgnoreCase("LinearRing")){ |
349 | 349 |
coords = ((LineString)geom).getCoordinates(); |
... | ... | |
357 | 357 |
LineString hole = polygon.getInteriorRingN(i); |
358 | 358 |
newHoles[i] = (LinearRing) snap(hole); |
359 | 359 |
} |
360 |
return JtsUtil.geomFactory.createPolygon(snapedShell, newHoles);
|
|
360 |
return JtsUtil.GEOMETRY_FACTORY.createPolygon(snapedShell, newHoles);
|
|
361 | 361 |
} |
362 | 362 |
|
363 | 363 |
SnapCoordinateList snapCoordList = |
... | ... | |
441 | 441 |
} |
442 | 442 |
|
443 | 443 |
|
444 |
public boolean isClosed(Geometry a) { |
|
445 |
Coordinate[] coords = a.getCoordinates(); |
|
446 |
Coordinate firstPoint = coords[0]; |
|
447 |
Coordinate lastPoint = coords[coords.length - 1]; |
|
448 |
return SnapCGAlgorithms.snapEquals2D(firstPoint, lastPoint, |
|
449 |
snapTolerance); |
|
450 |
} |
|
451 |
|
|
452 | 444 |
/** |
453 | 445 |
* If geometry 'a' is not exactly closed, but its extremes are |
454 | 446 |
* in a snap radius, its snap the last point to the first point of the |
... | ... | |
460 | 452 |
Coordinate[] coords = a.getCoordinates(); |
461 | 453 |
Coordinate firstPoint = coords[0]; |
462 | 454 |
Coordinate lastPoint = coords[coords.length - 1]; |
463 |
if(!firstPoint.equals2D(lastPoint) && isClosed(a)){
|
|
455 |
if(!firstPoint.equals2D(lastPoint) && JtsUtil.isClosed(a, snapTolerance)){
|
|
464 | 456 |
CoordinateList coordList = new CoordinateList(coords); |
465 | 457 |
coordList.set(coords.length - 1, coords[0]); |
466 | 458 |
// return createGeometry(coordList.toCoordinateArray(), a); |
... | ... | |
470 | 462 |
return a; |
471 | 463 |
} |
472 | 464 |
|
473 |
public static boolean isClosed(Geometry a, double snap){ |
|
474 |
Coordinate[] coords = a.getCoordinates(); |
|
475 |
Coordinate firstPoint = coords[0]; |
|
476 |
Coordinate lastPoint = coords[coords.length - 1]; |
|
477 |
return SnapCGAlgorithms.snapEquals2D(firstPoint, lastPoint, snap); |
|
478 |
} |
|
479 | 465 |
|
480 |
|
|
481 | 466 |
/** |
482 | 467 |
* Snaps coordinates in srcPts with coordinates of snapPts. |
483 | 468 |
* This method forces the snap: the points of srcPoints are shifted to |
trunk/libraries/libTopology/src/org/gvsig/jts/LineStringSelfIntersectionChecker.java | ||
---|---|---|
158 | 158 |
{ |
159 | 159 |
//the coordinate is equal to one of the nodes of a lineString |
160 | 160 |
//if the lineString is not closed, it could not be proper |
161 |
if(GeometrySnapper.isClosed(lineString, snapTolerance))
|
|
161 |
if(JtsUtil.isClosed(lineString, snapTolerance))
|
|
162 | 162 |
solution = true; |
163 | 163 |
}// if |
164 | 164 |
// }// if |
trunk/libraries/libTopology/src/org/gvsig/jts/LineStringSplitter.java | ||
---|---|---|
113 | 113 |
Polygonizer polygonizer = new Polygonizer(); |
114 | 114 |
LineString[] lineStrings = splitSimple(lineString, splitPoints); |
115 | 115 |
|
116 |
ArrayList closedLineStrings = new ArrayList();
|
|
117 |
ArrayList unclosedLineStrings = new ArrayList();
|
|
116 |
ArrayList<LineString> closedLineStrings = new ArrayList<LineString>();
|
|
117 |
ArrayList<LineString> unclosedLineStrings = new ArrayList<LineString>();
|
|
118 | 118 |
|
119 | 119 |
for(int i = 0; i < lineStrings.length; i++){ |
120 | 120 |
LineString geom = lineStrings[i]; |
121 |
if(GeometrySnapper.isClosed(geom, snapTolerance)){
|
|
121 |
if(JtsUtil.isClosed(geom, snapTolerance)){
|
|
122 | 122 |
closedLineStrings.add(geom); |
123 | 123 |
}else{ |
124 | 124 |
unclosedLineStrings.add(geom); |
... | ... | |
133 | 133 |
unclosedLineStrings.toArray(unclosedLS); |
134 | 134 |
GeometrySnapper snapper = new GeometrySnapper(snapTolerance); |
135 | 135 |
Geometry[] snappedLS = snapper.snap(unclosedLS); |
136 |
List snappedList = Arrays.asList(snappedLS); |
|
136 |
List<Geometry> snappedList = Arrays.asList(snappedLS);
|
|
137 | 137 |
|
138 | 138 |
|
139 | 139 |
polygonizer.add(snappedList); |
... | ... | |
159 | 159 |
//FIXME Introduce snap tolerance concept |
160 | 160 |
|
161 | 161 |
private static LineString[] splitUnclosedLineString(LineString lineString, |
162 |
Coordinate[] splitPoints) { |
|
162 |
Coordinate[] splitPoints, double snapTolerance) {
|
|
163 | 163 |
|
164 | 164 |
ArrayList lineStringList = new ArrayList(); |
165 | 165 |
RobustLengthIndexedLine lengthLine = new RobustLengthIndexedLine(lineString); |
166 |
ArrayList nodeIntersections = new ArrayList();
|
|
166 |
ArrayList<LineIntersection> nodeIntersections = new ArrayList<LineIntersection>();
|
|
167 | 167 |
double linearReferencingIndex = 0d; |
168 | 168 |
for (int i = 0; i < splitPoints.length; i++) { |
169 | 169 |
Coordinate coord = splitPoints[i]; |
... | ... | |
348 | 348 |
Coordinate[] duplicatedSelfIntersections = duplicateSelfIntersections(splitPoints); |
349 | 349 |
//TODO Create a test case for a linestring not closed for precision reasons |
350 | 350 |
//but closed with a given snap tolerance |
351 |
if(GeometrySnapper.isClosed(lineString, snapTolerance)){
|
|
351 |
if(JtsUtil.isClosed(lineString, snapTolerance)){
|
|
352 | 352 |
// if (lineString.isClosed()) { |
353 | 353 |
return splitClosedLineString(lineString, |
354 | 354 |
duplicatedSelfIntersections, snapTolerance); |
355 | 355 |
} else { |
356 | 356 |
return splitUnclosedLineString(lineString, |
357 |
duplicatedSelfIntersections); |
|
357 |
duplicatedSelfIntersections, snapTolerance);
|
|
358 | 358 |
} |
359 | 359 |
|
360 | 360 |
} |
trunk/libraries/libTopology/src/org/gvsig/jts/GeometryCracker.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 |
*/ |
|
49 |
package org.gvsig.jts; |
|
50 |
|
|
51 |
import com.vividsolutions.jts.algorithms.SnapCGAlgorithms; |
|
52 |
import com.vividsolutions.jts.geom.Coordinate; |
|
53 |
import com.vividsolutions.jts.geom.CoordinateList; |
|
54 |
import com.vividsolutions.jts.geom.Geometry; |
|
55 |
import com.vividsolutions.jts.geom.GeometryCollection; |
|
56 |
import com.vividsolutions.jts.geom.LineSegment; |
|
57 |
import com.vividsolutions.jts.geom.LineString; |
|
58 |
import com.vividsolutions.jts.geom.LinearRing; |
|
59 |
import com.vividsolutions.jts.geom.Point; |
|
60 |
import com.vividsolutions.jts.geom.Polygon; |
|
61 |
|
|
62 |
/** |
|
63 |
* Cracks the geometries of a topology's layers to force the sharing of |
|
64 |
* coordinates. |
|
65 |
* |
|
66 |
* Crack process consist in insert points in a segment when the distance of this |
|
67 |
* segment with a given coordinate is less than the snap tolerance. |
|
68 |
* |
|
69 |
* So GeometryCracker doesnt compute intersections between segments |
|
70 |
* and inserts new coordinates there. |
|
71 |
* |
|
72 |
* GeometryCracker only insert new coordinates in segments when these coordinates |
|
73 |
* are shared geometry (they are vertices of other geometries) |
|
74 |
* |
|
75 |
*/ |
|
76 |
public class GeometryCracker { |
|
77 |
|
|
78 |
private LineSegment seg = new LineSegment(); |
|
79 |
|
|
80 |
private double snapTolerance; |
|
81 |
|
|
82 |
public GeometryCracker(double snapTolerance) { |
|
83 |
this.snapTolerance = snapTolerance; |
|
84 |
} |
|
85 |
|
|
86 |
public Geometry[] crackGeometries(Geometry[] geoms) { |
|
87 |
Geometry[] solution = new Geometry[geoms.length]; |
|
88 |
|
|
89 |
for (int i = 0; i < geoms.length; i++) { |
|
90 |
Geometry geom = geoms[i]; |
|
91 |
solution[i] = geom; |
|
92 |
for (int k = 0; k < geoms.length; k++) { |
|
93 |
Geometry geom2 = geoms[k]; |
|
94 |
if (i == k) |
|
95 |
continue; |
|
96 |
solution[i] = crackGeometries(solution[i], geom2); |
|
97 |
}// for k |
|
98 |
}// for i |
|
99 |
return solution; |
|
100 |
} |
|
101 |
|
|
102 |
/** |
|
103 |
* "Cracks" a geometry a with the points of a given geometry b. |
|
104 |
* |
|
105 |
* @param a |
|
106 |
* @param b |
|
107 |
* @param snapTolerance |
|
108 |
* @return |
|
109 |
*/ |
|
110 |
public static Geometry crackGeometries(Geometry a, Geometry b, double snapTolerance) { |
|
111 |
GeometryCracker cracker = new GeometryCracker(snapTolerance); |
|
112 |
return cracker.crackGeometries(a, b); |
|
113 |
} |
|
114 |
|
|
115 |
|
|
116 |
public Geometry crackGeometries(Geometry a, Geometry b){ |
|
117 |
Geometry solution = a; |
|
118 |
if(a.getGeometryType().equalsIgnoreCase("Polygon")){ |
|
119 |
Polygon polygonA = (Polygon)a; |
|
120 |
if(b.getGeometryType().equalsIgnoreCase("Point") || |
|
121 |
b.getGeometryType().equalsIgnoreCase("LineString") || |
|
122 |
b.getGeometryType().equalsIgnoreCase("LinearRing")){ |
|
123 |
solution = crackPolygonWithPointOrLine(polygonA, b); |
|
124 |
}else if(b.getGeometryType().equalsIgnoreCase("Polygon")){ |
|
125 |
Polygon polygonB = (Polygon)b; |
|
126 |
solution = crackPolygonWithPolygon(polygonA, polygonB); |
|
127 |
}else if(b instanceof GeometryCollection){ |
|
128 |
GeometryCollection collection = (GeometryCollection)b; |
|
129 |
for(int i = 0; i < collection.getNumGeometries(); i++){ |
|
130 |
Geometry geometry = collection.getGeometryN(i); |
|
131 |
polygonA = (Polygon) crackGeometries(polygonA, geometry); |
|
132 |
}//for |
|
133 |
solution = polygonA; |
|
134 |
}//else |
|
135 |
|
|
136 |
}else if(a.getGeometryType().equalsIgnoreCase("LineString") || a.getGeometryType().equalsIgnoreCase("LinearRing")){ |
|
137 |
LineString lineStringA = (LineString) a; |
|
138 |
if(b.getGeometryType().equalsIgnoreCase("LineString") || b.getGeometryType().equalsIgnoreCase("LinearRing") || b instanceof Point){ |
|
139 |
solution = crackLineStringWithPointOrLine(lineStringA, b); |
|
140 |
}else if(b instanceof Polygon){ |
|
141 |
Polygon polygonB = (Polygon) b; |
|
142 |
solution = crackLineStringWithPolygon(lineStringA, polygonB); |
|
143 |
}else if(b instanceof GeometryCollection){ |
|
144 |
GeometryCollection collection = (GeometryCollection)b; |
|
145 |
for(int i = 0; i < collection.getNumGeometries(); i++){ |
|
146 |
Geometry geometry = collection.getGeometryN(i); |
|
147 |
lineStringA = (LineString) crackGeometries(lineStringA, geometry); |
|
148 |
}//for |
|
149 |
solution = lineStringA; |
|
150 |
}//else |
|
151 |
|
|
152 |
}else if(a.getGeometryType().equalsIgnoreCase("Point")){ |
|
153 |
solution = a; |
|
154 |
}else if(a instanceof GeometryCollection){ |
|
155 |
GeometryCollection collection = (GeometryCollection)a; |
|
156 |
Geometry[] geomArray = new Geometry[collection.getNumGeometries()]; |
|
157 |
for(int i = 0; i < collection.getNumGeometries(); i++){ |
|
158 |
Geometry geometry = collection.getGeometryN(i); |
|
159 |
Geometry crackedGeometry = crackGeometries(geometry, b); |
|
160 |
geomArray[i] = crackedGeometry; |
|
161 |
}//for |
|
162 |
solution = JtsUtil.geomFactory.createGeometryCollection(geomArray); |
|
163 |
}//GeometryCollection |
|
164 |
return solution; |
|
165 |
} |
|
166 |
|
|
167 |
/** |
|
168 |
* Cracks the passed polygon with the point parameter |
|
169 |
* @param point |
|
170 |
* @param polygon |
|
171 |
* @return |
|
172 |
*/ |
|
173 |
private Geometry crackPolygonWithPointOrLine(Polygon polygon, Geometry geometry){ |
|
174 |
if(! (geometry instanceof LineString) && ! (geometry instanceof Point)) |
|
175 |
throw new IllegalArgumentException("Este metodo solo funciona con puntos y lineas y se recibio "+geometry.getGeometryType()); |
|
176 |
LinearRing shell = (LinearRing) polygon.getExteriorRing(); |
|
177 |
LinearRing crackedShell = (LinearRing) JtsUtil.createGeometry(crackTo(shell.getCoordinates(), geometry.getCoordinates()), "LINEARRING"); |
|
178 |
int numberOfHoles = polygon.getNumInteriorRing(); |
|
179 |
LinearRing[] crackedHoles = new LinearRing[numberOfHoles]; |
|
180 |
for(int i = 0; i < numberOfHoles; i++){ |
|
181 |
LinearRing hole = (LinearRing) polygon.getInteriorRingN(i); |
|
182 |
LinearRing crackedHole = (LinearRing) JtsUtil.createGeometry(crackTo(hole.getCoordinates(), geometry.getCoordinates()), "LINEARRING"); |
|
183 |
crackedHoles[i] = crackedHole; |
|
184 |
} |
|
185 |
return JtsUtil.geomFactory.createPolygon(crackedShell, crackedHoles); |
|
186 |
} |
|
187 |
|
|
188 |
private Geometry crackLineStringWithPointOrLine(LineString lineA, Geometry geometry){ |
|
189 |
if(! (geometry instanceof LineString) && ! (geometry instanceof Point)) |
|
190 |
throw new IllegalArgumentException("Este metodo solo funciona con puntos y lineas y se recibio "+geometry.getGeometryType()); |
|
191 |
Coordinate[] newCoordsA = crackTo(lineA.getCoordinates(), geometry.getCoordinates()); |
|
192 |
//we call to lineA.getGeometryType because it could be a LineString or a LinearRing |
|
193 |
return JtsUtil.createGeometry(newCoordsA, lineA.getGeometryType()); |
|
194 |
} |
|
195 |
|
|
196 |
|
|
197 |
|
|
198 |
private Geometry crackLineStringWithPolygon(LineString line, Polygon polygon){ |
|
199 |
LinearRing shell = (LinearRing) polygon.getExteriorRing(); |
|
200 |
Coordinate[] lineStringCracked = crackTo(line.getCoordinates(), shell.getCoordinates()); |
|
201 |
int numberOfHoles = polygon.getNumInteriorRing(); |
|
202 |
for(int i = 0; i < numberOfHoles; i++){ |
|
203 |
LinearRing hole = (LinearRing) polygon.getInteriorRingN(i); |
|
204 |
lineStringCracked = crackTo(lineStringCracked, hole.getCoordinates()); |
|
205 |
} |
|
206 |
return JtsUtil.createGeometry(lineStringCracked, line.getGeometryType()); |
|
207 |
} |
|
208 |
|
|
209 |
|
|
210 |
private Geometry crackPolygonWithPolygon(Polygon polyA, Polygon polyB){ |
|
211 |
LinearRing shell = (LinearRing) polyB.getExteriorRing(); |
|
212 |
Polygon crackedPolygon = (Polygon) crackPolygonWithPointOrLine(polyA, shell); |
|
213 |
int numberOfHoles = polyB.getNumInteriorRing(); |
|
214 |
for(int i = 0; i < numberOfHoles; i++){ |
|
215 |
LinearRing hole = (LinearRing) polyB.getInteriorRingN(i); |
|
216 |
crackedPolygon = (Polygon) crackPolygonWithPointOrLine(crackedPolygon, hole); |
|
217 |
} |
|
218 |
return crackedPolygon; |
|
219 |
} |
|
220 |
|
|
221 |
|
|
222 |
|
|
223 |
|
|
224 |
/* |
|
225 |
* This code is extracted from the class LineStringSnapper of JTS |
|
226 |
*/ |
|
227 |
private Coordinate[] crackTo(Coordinate[] srcPts, Coordinate[] snapPts) { |
|
228 |
CoordinateList coordList = new CoordinateList(srcPts); |
|
229 |
crackSegments(coordList, snapPts); |
|
230 |
Coordinate[] newPts = coordList.toCoordinateArray(); |
|
231 |
return newPts; |
|
232 |
} |
|
233 |
|
|
234 |
private void crackSegments(CoordinateList srcCoords, Coordinate[] snapPts) { |
|
235 |
int distinctPtCount = snapPts.length; |
|
236 |
Coordinate firstPoint = snapPts[0]; |
|
237 |
Coordinate lastPoint = snapPts[snapPts.length - 1]; |
|
238 |
if (SnapCGAlgorithms.snapEquals2D(firstPoint, lastPoint, snapTolerance)){ |
|
239 |
if(distinctPtCount > 1)//necessary because with snapPts.length the algorithm doesnt work |
|
240 |
distinctPtCount = snapPts.length - 1; |
|
241 |
} |
|
242 |
for (int i = 0; i < distinctPtCount; i++) { |
|
243 |
Coordinate snapPt = snapPts[i]; |
|
244 |
int index = findSegmentIndexToSnap(snapPt, srcCoords); |
|
245 |
if (index >= 0) { |
|
246 |
seg.p0 = srcCoords.getCoordinate(index); |
|
247 |
seg.p1 = srcCoords.getCoordinate(index +1); |
|
248 |
Coordinate newCoordinate = seg.closestPoint(snapPt); |
|
249 |
srcCoords.add(index + 1, newCoordinate, false); |
|
250 |
}// if |
|
251 |
}// for i |
|
252 |
} |
|
253 |
|
|
254 |
private int findSegmentIndexToSnap(Coordinate snapPt, |
|
255 |
CoordinateList srcCoords) { |
|
256 |
double minDist = Double.MAX_VALUE; |
|
257 |
int snapIndex = -1; |
|
258 |
for (int i = 0; i < srcCoords.size() - 1; i++) { |
|
259 |
seg.p0 = (Coordinate) srcCoords.get(i); |
|
260 |
seg.p1 = (Coordinate) srcCoords.get(i + 1); |
|
261 |
|
|
262 |
if (SnapCGAlgorithms.snapEquals2D(seg.p0, snapPt, snapTolerance) |
|
263 |
|| SnapCGAlgorithms.snapEquals2D(seg.p1, snapPt, |
|
264 |
snapTolerance)) |
|
265 |
return -1; |
|
266 |
double dist = seg.distance(snapPt); |
|
267 |
if (dist <= snapTolerance && dist < minDist) { |
|
268 |
minDist = dist; |
|
269 |
snapIndex = i; |
|
270 |
} |
|
271 |
}//for |
|
272 |
return snapIndex; |
|
273 |
} |
|
274 |
|
|
275 |
} |
|
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 com.vividsolutions.jts.algorithms.SnapCGAlgorithms; |
|
52 |
import com.vividsolutions.jts.geom.Coordinate; |
|
53 |
import com.vividsolutions.jts.geom.CoordinateList; |
|
54 |
import com.vividsolutions.jts.geom.Geometry; |
|
55 |
import com.vividsolutions.jts.geom.GeometryCollection; |
|
56 |
import com.vividsolutions.jts.geom.LineSegment; |
|
57 |
import com.vividsolutions.jts.geom.LineString; |
|
58 |
import com.vividsolutions.jts.geom.LinearRing; |
|
59 |
import com.vividsolutions.jts.geom.Point; |
|
60 |
import com.vividsolutions.jts.geom.Polygon; |
|
61 |
|
|
62 |
/** |
|
63 |
* Cracks the geometries of a topology's layers to force the sharing of |
|
64 |
* coordinates. |
|
65 |
* |
|
66 |
* Crack process consist in insert points in a segment when the distance of this |
|
67 |
* segment with a given coordinate is less than the snap tolerance. |
|
68 |
* |
|
69 |
* So GeometryCracker doesnt compute intersections between segments |
|
70 |
* and inserts new coordinates there. |
|
71 |
* |
|
72 |
* GeometryCracker only insert new coordinates in segments when these coordinates |
|
73 |
* are shared geometry (they are vertices of other geometries) |
|
74 |
* |
|
75 |
*/ |
|
76 |
public class GeometryCracker { |
|
77 |
|
|
78 |
private LineSegment seg = new LineSegment(); |
|
79 |
|
|
80 |
private double snapTolerance; |
|
81 |
|
|
82 |
public GeometryCracker(double snapTolerance) { |
|
83 |
this.snapTolerance = snapTolerance; |
|
84 |
} |
|
85 |
|
|
86 |
public Geometry[] crackGeometries(Geometry[] geoms) { |
|
87 |
Geometry[] solution = new Geometry[geoms.length]; |
|
88 |
|
|
89 |
for (int i = 0; i < geoms.length; i++) { |
|
90 |
Geometry geom = geoms[i]; |
|
91 |
solution[i] = geom; |
|
92 |
for (int k = 0; k < geoms.length; k++) { |
|
93 |
Geometry geom2 = geoms[k]; |
|
94 |
if (i == k) |
|
95 |
continue; |
|
96 |
solution[i] = crackGeometries(solution[i], geom2); |
|
97 |
}// for k |
|
98 |
}// for i |
|
99 |
return solution; |
|
100 |
} |
|
101 |
|
|
102 |
/** |
|
103 |
* "Cracks" a geometry a with the points of a given geometry b. |
|
104 |
* |
|
105 |
* @param a |
|
106 |
* @param b |
|
107 |
* @param snapTolerance |
|
108 |
* @return |
|
109 |
*/ |
|
110 |
public static Geometry crackGeometries(Geometry a, Geometry b, double snapTolerance) { |
|
111 |
GeometryCracker cracker = new GeometryCracker(snapTolerance); |
|
112 |
return cracker.crackGeometries(a, b); |
|
113 |
} |
|
114 |
|
|
115 |
|
|
116 |
public Geometry crackGeometries(Geometry a, Geometry b){ |
|
117 |
Geometry solution = a; |
|
118 |
if(a.getGeometryType().equalsIgnoreCase("Polygon")){ |
|
119 |
Polygon polygonA = (Polygon)a; |
|
120 |
if(b.getGeometryType().equalsIgnoreCase("Point") || |
|
121 |
b.getGeometryType().equalsIgnoreCase("LineString") || |
|
122 |
b.getGeometryType().equalsIgnoreCase("LinearRing")){ |
|
123 |
solution = crackPolygonWithPointOrLine(polygonA, b); |
|
124 |
}else if(b.getGeometryType().equalsIgnoreCase("Polygon")){ |
|
125 |
Polygon polygonB = (Polygon)b; |
|
126 |
solution = crackPolygonWithPolygon(polygonA, polygonB); |
|
127 |
}else if(b instanceof GeometryCollection){ |
|
128 |
GeometryCollection collection = (GeometryCollection)b; |
|
129 |
for(int i = 0; i < collection.getNumGeometries(); i++){ |
|
130 |
Geometry geometry = collection.getGeometryN(i); |
|
131 |
polygonA = (Polygon) crackGeometries(polygonA, geometry); |
|
132 |
}//for |
|
133 |
solution = polygonA; |
|
134 |
}//else |
|
135 |
|
|
136 |
}else if(a.getGeometryType().equalsIgnoreCase("LineString") || a.getGeometryType().equalsIgnoreCase("LinearRing")){ |
|
137 |
LineString lineStringA = (LineString) a; |
|
138 |
if(b.getGeometryType().equalsIgnoreCase("LineString") || b.getGeometryType().equalsIgnoreCase("LinearRing") || b instanceof Point){ |
|
139 |
solution = crackLineStringWithPointOrLine(lineStringA, b); |
|
140 |
}else if(b instanceof Polygon){ |
|
141 |
Polygon polygonB = (Polygon) b; |
|
142 |
solution = crackLineStringWithPolygon(lineStringA, polygonB); |
|
143 |
}else if(b instanceof GeometryCollection){ |
|
144 |
GeometryCollection collection = (GeometryCollection)b; |
|
145 |
for(int i = 0; i < collection.getNumGeometries(); i++){ |
|
146 |
Geometry geometry = collection.getGeometryN(i); |
|
147 |
lineStringA = (LineString) crackGeometries(lineStringA, geometry); |
|
148 |
}//for |
|
149 |
solution = lineStringA; |
|
150 |
}//else |
|
151 |
|
|
152 |
}else if(a.getGeometryType().equalsIgnoreCase("Point")){ |
|
153 |
solution = a; |
|
154 |
}else if(a instanceof GeometryCollection){ |
|
155 |
GeometryCollection collection = (GeometryCollection)a; |
|
156 |
Geometry[] geomArray = new Geometry[collection.getNumGeometries()]; |
|
157 |
for(int i = 0; i < collection.getNumGeometries(); i++){ |
|
158 |
Geometry geometry = collection.getGeometryN(i); |
|
159 |
Geometry crackedGeometry = crackGeometries(geometry, b); |
|
160 |
geomArray[i] = crackedGeometry; |
|
161 |
}//for |
|
162 |
solution = JtsUtil.GEOMETRY_FACTORY.createGeometryCollection(geomArray); |
|
163 |
}//GeometryCollection |
|
164 |
return solution; |
|
165 |
} |
|
166 |
|
|
167 |
/** |
|
168 |
* Cracks the passed polygon with the point parameter |
|
169 |
* @param point |
|
170 |
* @param polygon |
|
171 |
* @return |
|
172 |
*/ |
|
173 |
private Geometry crackPolygonWithPointOrLine(Polygon polygon, Geometry geometry){ |
|
174 |
if(! (geometry instanceof LineString) && ! (geometry instanceof Point)) |
|
175 |
throw new IllegalArgumentException("Este metodo solo funciona con puntos y lineas y se recibio "+geometry.getGeometryType()); |
|
176 |
LinearRing shell = (LinearRing) polygon.getExteriorRing(); |
|
177 |
LinearRing crackedShell = (LinearRing) JtsUtil.createGeometry(crackTo(shell.getCoordinates(), geometry.getCoordinates()), "LINEARRING"); |
|
178 |
int numberOfHoles = polygon.getNumInteriorRing(); |
|
179 |
LinearRing[] crackedHoles = new LinearRing[numberOfHoles]; |
|
180 |
for(int i = 0; i < numberOfHoles; i++){ |
|
181 |
LinearRing hole = (LinearRing) polygon.getInteriorRingN(i); |
|
182 |
LinearRing crackedHole = (LinearRing) JtsUtil.createGeometry(crackTo(hole.getCoordinates(), geometry.getCoordinates()), "LINEARRING"); |
|
183 |
crackedHoles[i] = crackedHole; |
|
184 |
} |
|
185 |
return JtsUtil.GEOMETRY_FACTORY.createPolygon(crackedShell, crackedHoles); |
|
186 |
} |
|
187 |
|
|
188 |
private Geometry crackLineStringWithPointOrLine(LineString lineA, Geometry geometry){ |
|
189 |
if(! (geometry instanceof LineString) && ! (geometry instanceof Point)) |
|
190 |
throw new IllegalArgumentException("Este metodo solo funciona con puntos y lineas y se recibio "+geometry.getGeometryType()); |
|
191 |
Coordinate[] newCoordsA = crackTo(lineA.getCoordinates(), geometry.getCoordinates()); |
|
192 |
//we call to lineA.getGeometryType because it could be a LineString or a LinearRing |
|
193 |
return JtsUtil.createGeometry(newCoordsA, lineA.getGeometryType()); |
|
194 |
} |
|
195 |
|
|
196 |
|
|
197 |
|
|
198 |
private Geometry crackLineStringWithPolygon(LineString line, Polygon polygon){ |
|
199 |
LinearRing shell = (LinearRing) polygon.getExteriorRing(); |
|
200 |
Coordinate[] lineStringCracked = crackTo(line.getCoordinates(), shell.getCoordinates()); |
|
201 |
int numberOfHoles = polygon.getNumInteriorRing(); |
|
202 |
for(int i = 0; i < numberOfHoles; i++){ |
|
203 |
LinearRing hole = (LinearRing) polygon.getInteriorRingN(i); |
|
204 |
lineStringCracked = crackTo(lineStringCracked, hole.getCoordinates()); |
|
205 |
} |
|
206 |
return JtsUtil.createGeometry(lineStringCracked, line.getGeometryType()); |
|
207 |
} |
|
208 |
|
|
209 |
|
|
210 |
private Geometry crackPolygonWithPolygon(Polygon polyA, Polygon polyB){ |
|
211 |
LinearRing shell = (LinearRing) polyB.getExteriorRing(); |
|
212 |
Polygon crackedPolygon = (Polygon) crackPolygonWithPointOrLine(polyA, shell); |
|
213 |
int numberOfHoles = polyB.getNumInteriorRing(); |
|
214 |
for(int i = 0; i < numberOfHoles; i++){ |
|
215 |
LinearRing hole = (LinearRing) polyB.getInteriorRingN(i); |
|
216 |
crackedPolygon = (Polygon) crackPolygonWithPointOrLine(crackedPolygon, hole); |
|
217 |
} |
|
218 |
return crackedPolygon; |
|
219 |
} |
|
220 |
|
|
221 |
|
|
222 |
|
|
223 |
|
|
224 |
/* |
|
225 |
* This code is extracted from the class LineStringSnapper of JTS |
|
226 |
*/ |
|
227 |
private Coordinate[] crackTo(Coordinate[] srcPts, Coordinate[] snapPts) { |
|
228 |
CoordinateList coordList = new CoordinateList(srcPts); |
|
229 |
crackSegments(coordList, snapPts); |
|
230 |
Coordinate[] newPts = coordList.toCoordinateArray(); |
|
231 |
return newPts; |
|
232 |
} |
|
233 |
|
|
234 |
private void crackSegments(CoordinateList srcCoords, Coordinate[] snapPts) { |
|
235 |
int distinctPtCount = snapPts.length; |
|
236 |
Coordinate firstPoint = snapPts[0]; |
|
237 |
Coordinate lastPoint = snapPts[snapPts.length - 1]; |
|
238 |
if (SnapCGAlgorithms.snapEquals2D(firstPoint, lastPoint, snapTolerance)){ |
|
239 |
if(distinctPtCount > 1)//necessary because with snapPts.length the algorithm doesnt work |
|
240 |
distinctPtCount = snapPts.length - 1; |
|
241 |
} |
|
242 |
for (int i = 0; i < distinctPtCount; i++) { |
|
243 |
Coordinate snapPt = snapPts[i]; |
|
244 |
int index = findSegmentIndexToSnap(snapPt, srcCoords); |
|
245 |
if (index >= 0) { |
|
246 |
seg.p0 = srcCoords.getCoordinate(index); |
|
247 |
seg.p1 = srcCoords.getCoordinate(index +1); |
|
248 |
Coordinate newCoordinate = seg.closestPoint(snapPt); |
|
249 |
srcCoords.add(index + 1, newCoordinate, false); |
|
250 |
}// if |
|
251 |
}// for i |
|
252 |
} |
|
253 |
|
|
254 |
private int findSegmentIndexToSnap(Coordinate snapPt, |
|
255 |
CoordinateList srcCoords) { |
|
256 |
double minDist = Double.MAX_VALUE; |
|
257 |
int snapIndex = -1; |
|
258 |
for (int i = 0; i < srcCoords.size() - 1; i++) { |
|
259 |
seg.p0 = (Coordinate) srcCoords.get(i); |
|
260 |
seg.p1 = (Coordinate) srcCoords.get(i + 1); |
|
261 |
|
|
262 |
if (SnapCGAlgorithms.snapEquals2D(seg.p0, snapPt, snapTolerance) |
|
263 |
|| SnapCGAlgorithms.snapEquals2D(seg.p1, snapPt, |
|
264 |
snapTolerance)) |
|
265 |
return -1; |
|
266 |
double dist = seg.distance(snapPt); |
|
267 |
if (dist <= snapTolerance && dist < minDist) { |
|
268 |
minDist = dist; |
|
269 |
snapIndex = i; |
|
270 |
} |
|
271 |
}//for |
|
272 |
return snapIndex; |
|
273 |
} |
|
274 |
|
|
275 |
} |
Also available in: Unified diff