Revision 25630 trunk/libraries/libTopology/src/org/gvsig/topology/errorfixes/ExtendDangleToNearestBoundaryPointFix.java
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