Revision 25630 trunk/libraries/libTopology/src/org/gvsig/topology/errorfixes/ExtendDangleToNearestBoundaryPointFix.java

View differences:

ExtendDangleToNearestBoundaryPointFix.java
48 48
*/
49 49
package org.gvsig.topology.errorfixes;
50 50

  
51
import java.awt.geom.Rectangle2D;
52
import java.util.ArrayList;
53
import java.util.List;
54
import java.util.Map;
55

  
56
import org.gvsig.exceptions.BaseException;
57
import org.gvsig.fmap.core.FLyrUtil;
58
import org.gvsig.fmap.core.NewFConverter;
59
import org.gvsig.jts.JtsUtil;
51 60
import org.gvsig.topology.Messages;
61
import org.gvsig.topology.TopologyError;
62
import org.gvsig.util.GNumberParameter;
63
import org.gvsig.util.GParameter;
52 64

  
65
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
66
import com.iver.cit.gvsig.drivers.featureiterators.FeatureListIntIterator;
67
import com.iver.cit.gvsig.fmap.core.FGeometry;
68
import com.iver.cit.gvsig.fmap.core.FPoint2D;
69
import com.iver.cit.gvsig.fmap.core.IFeature;
70
import com.iver.cit.gvsig.fmap.core.IGeometry;
71
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
72
import com.iver.cit.gvsig.fmap.spatialindex.INearestNeighbourFinder;
73
import com.vividsolutions.jts.algorithms.SnapCGAlgorithms;
53 74
import com.vividsolutions.jts.geom.Coordinate;
54 75
import com.vividsolutions.jts.geom.Geometry;
76
import com.vividsolutions.jts.geom.GeometryCollection;
77
import com.vividsolutions.jts.geom.LineString;
78
import com.vividsolutions.jts.geom.Point;
79
import com.vividsolutions.jts.geom.util.LinearComponentExtracter;
80
import com.vividsolutions.jts.geom.util.GeometryEditor.CoordinateOperation;
55 81
import com.vividsolutions.jts.operation.distance.DistanceOp;
56 82

  
57 83
public class ExtendDangleToNearestBoundaryPointFix extends
58 84
		ExtendDangleToNearestVertexFix {
85
	
86
	public double searchRadius;
59 87

  
60 88
	public ExtendDangleToNearestBoundaryPointFix(double searchRadius) {
61 89
		super(searchRadius);
90
		this.searchRadius = searchRadius;
62 91
	}
63 92

  
64 93
	public ExtendDangleToNearestBoundaryPointFix() {
......
74 103
	public String getEditionDescription() {
75 104
		return Messages.getText("EXTEND_DANGLE_TO_BOUNDARY_FIX");
76 105
	}
106
	
107
	
108
	public List<IFeature>[] fixAlgorithm(TopologyError error) throws BaseException {
109
		FLyrVect originLyr = error.getOriginLayer();
110
		double clusterTolerance = error.getTopology().getClusterTolerance();
111
		FGeometry errorGeometry = (FGeometry) error.getGeometry();
112
		FPoint2D dangle = (FPoint2D) errorGeometry.getInternalShape();
113
		Coordinate jtsCoord = new Coordinate(dangle.getX(), dangle.getY());
114
		Point jtsDangle = JtsUtil.GEOMETRY_FACTORY.createPoint(jtsCoord);
115
		
116
		IFeature originFeature = error.getFeature1();
117
		
118
		IFeature nearestFeature = getNearestFeature(jtsDangle, originLyr, originFeature);
119
		
120
		if(nearestFeature != null){
121
			Geometry nearestJts = NewFConverter.toJtsGeometry(nearestFeature.getGeometry());
122
			Geometry originalJts = NewFConverter.toJtsGeometry(originFeature.getGeometry());
123
			
124
			Coordinate closestPoint = getClosestPoint(jtsDangle, nearestJts);
125
			double distance = DistanceOp.distance(jtsDangle, nearestJts);
126
			
127
			if(distance <= searchRadius){
128
				Geometry editedGeometry = extendGeometry(originalJts, jtsDangle.getCoordinate(), closestPoint, clusterTolerance);
129
				if(editedGeometry != null){
130
					IGeometry newGeom = NewFConverter.toFMap(editedGeometry);
131
					
132
					originFeature.setGeometry(newGeom);
133
					List<IFeature> editedFeatures = new ArrayList<IFeature>();
134
					editedFeatures.add(originFeature);
135
					return (List<IFeature>[]) new List[]{editedFeatures};
136
				}//if editedGeometry
137
			}//if distance	
138
			else{
139
				BaseException exception = new BaseException(){
140
					public String getFormatString(){
141
						return Messages.getText("Geometry_not_found_in_radius_search");
142
					}
143
					@Override
144
					protected Map values() {
145
						// TODO Auto-generated method stub
146
						return null;
147
					}};
148
				throw exception;
149
			}
150
		}//if nearest feature
151
		return null;
152
	}
153
	
154
	
155
	
156
	
157
	private Geometry extendGeometry(Geometry g, Coordinate dangle, final Coordinate closestPoint, double clusterTolerance){
158
		
159
		List<LineString> geometries2process = new ArrayList<LineString>();
160
		if (g instanceof LineString)
161
			geometries2process.add((LineString) g);
162
		else if (g instanceof GeometryCollection) {
163
			GeometryCollection geomCol = (GeometryCollection) g;
164
			List lines = LinearComponentExtracter.getLines(geomCol);
165
			geometries2process.addAll(lines);
166
		}
167
		
168
		for(int i = 0; i < geometries2process.size(); i++){
169
			LineString lineString = geometries2process.get(i);
170
			if(JtsUtil.isEndPoint(lineString, dangle, clusterTolerance)){
171
				int numPoints = lineString.getNumPoints();
172
				Coordinate start = lineString.getCoordinateN(0);
173
				Coordinate end = lineString.getCoordinateN(numPoints - 1);
174
				Geometry editedGeometry = null;
175
				if(SnapCGAlgorithms.snapEquals2D(dangle, start, clusterTolerance)){
176
					editedGeometry = JtsUtil.GEOMETRY_EDITOR.edit(lineString, new CoordinateOperation(){
177
						public Coordinate[] edit(Coordinate[] coordinates, Geometry geometry) {
178
							Coordinate[] newCoordinates = new Coordinate[coordinates.length + 1];
179
							System.arraycopy(coordinates, 0, newCoordinates, 1, coordinates.length);
180
							newCoordinates[0] = closestPoint;
181
							return newCoordinates;
182
						}});
183
					
184
				}else{
185
					editedGeometry = JtsUtil.GEOMETRY_EDITOR.edit(lineString, new CoordinateOperation(){
186
						public Coordinate[] edit(Coordinate[] coordinates, Geometry geometry) {
187
							Coordinate[] newCoordinates = new Coordinate[coordinates.length + 1];
188
							System.arraycopy(coordinates, 0, newCoordinates, 0, coordinates.length);
189
							newCoordinates[coordinates.length] = closestPoint;
190
							return newCoordinates;
191
						}});
192
				}
193
				return editedGeometry;
194
			}//if isEndPoint
195
		}//for
196
		//at this point we havent found a linestring end point for the dangle error
197
		//TODO launch inconsistent exception?
198
		return null;
199
	}
200

  
201
	
202
	
203
	private IFeature getNearestFeature(Point jtsDangle, FLyrVect originLyr, IFeature originFeature) throws ReadDriverException{
204
//		IGeometry originalGeometry = originFeature.getGeometry();
205
//		Geometry originalJts = NewFConverter.toJtsGeometry(originalGeometry);
206
		
207
		INearestNeighbourFinder nnFinder =
208
			FLyrUtil.getNearestNeighbourFinder(originLyr);
209
		
210
		int numberOfNearest = 2;
211
		Rectangle2D dangleRect = new Rectangle2D.Double(jtsDangle.getX(), jtsDangle.getY(), 1, 1);
212
//		List nearestIndexes = nnFinder.
213
//			findNNearest(numberOfNearest, new Point2D.Double(dangle.getX(), dangle.getY()));
214
		List nearestIndexes = nnFinder.findNNearest(numberOfNearest, dangleRect);
215
		
216
		//we look for the nearest neighbour to the dangle, excepting the originFeature
217
		//if the distance to the point is lesser than the search radius, we snap it
218
		double nearestDistance = Double.MAX_VALUE;
219
		
220
		FeatureListIntIterator it = new FeatureListIntIterator(nearestIndexes, originLyr.getSource() );
221
		IFeature nearestFeature = null;
222
		while(it.hasNext()){
223
			IFeature feature = it.next();
224
			if(feature.getID().equalsIgnoreCase(originFeature.getID()))
225
				continue;
226
			IGeometry igeometry = feature.getGeometry();
227
			Geometry jtsGeo = igeometry.toJTSGeometry();
228
			double dist = jtsGeo.distance(jtsDangle);
229
//			double dist = originalJts.distance(jtsGeo);
230
			if (dist <= nearestDistance) {
231
				// by adding <=, we follow the convention that
232
				// if two features are at the same distance, take
233
				// the last as nearest neighbour
234
				nearestDistance = dist;
235
				nearestFeature = feature;
236
			}// if
237
		}//while
238
		return nearestFeature;
239
	}
240
	
241

  
242
	public double getSearchRadius() {
243
		return searchRadius;
244
	}
245

  
246
	public void setSearchRadius(double searchRadius) {
247
		this.searchRadius = searchRadius;
248
	}
249

  
250
	
251
	public GParameter[] getParameters() {
252
		GParameter[] parameters = new GParameter[1];
253
		parameters[0] = 
254
			new GNumberParameter("searchRadius", new Double(0d), this, false);
255
		return parameters;
256
	}
257

  
258
	public void setParameterValue(String paramName, Object value) {
259
		if(paramName.equals("searchRadius")){
260
			if(value.getClass().isAssignableFrom(Number.class)){
261
				this.searchRadius = ((Number)value).doubleValue();
262
			}
263
		}	
264
	}
265

  
77 266
}

Also available in: Unified diff