Revision 19632

View differences:

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