root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / hydrology / channelNetwork / ChannelNetworkAlgorithm.java @ 59
History | View | Annotate | Download (11.3 KB)
1 |
package es.unex.sextante.hydrology.channelNetwork; |
---|---|
2 |
|
3 |
import java.awt.geom.Point2D; |
4 |
import java.util.ArrayList; |
5 |
import java.util.Arrays; |
6 |
|
7 |
import com.vividsolutions.jts.geom.Coordinate; |
8 |
import com.vividsolutions.jts.geom.Geometry; |
9 |
import com.vividsolutions.jts.geom.GeometryFactory; |
10 |
|
11 |
import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue; |
12 |
import es.unex.sextante.core.AnalysisExtent; |
13 |
import es.unex.sextante.core.GeoAlgorithm; |
14 |
import es.unex.sextante.core.Sextante; |
15 |
import es.unex.sextante.dataObjects.IRasterLayer; |
16 |
import es.unex.sextante.dataObjects.IVectorLayer; |
17 |
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
18 |
import es.unex.sextante.exceptions.RepeatedParameterNameException; |
19 |
import es.unex.sextante.outputs.OutputVectorLayer; |
20 |
import es.unex.sextante.rasterWrappers.GridCell; |
21 |
|
22 |
public class ChannelNetworkAlgorithm |
23 |
extends
|
24 |
GeoAlgorithm { |
25 |
|
26 |
private final static int m_iOffsetX[] = { 0, 1, 1, 1, 0, -1, -1, -1 }; |
27 |
private final static int m_iOffsetY[] = { 1, 1, 0, -1, -1, -1, 0, 1 }; |
28 |
|
29 |
public static final String METHOD = "METHOD"; |
30 |
public static final String DEM = "DEM"; |
31 |
public static final String THRESHOLDLAYER = "THRESHOLDLAYER"; |
32 |
public static final String THRESHOLD = "THRESHOLD"; |
33 |
public static final String NETWORK = "NETWORK"; |
34 |
public static final String NETWORKVECT = "NETWORKVECT"; |
35 |
|
36 |
private int m_iMethod; |
37 |
private int m_iNX, m_iNY; |
38 |
private double m_dThreshold; |
39 |
|
40 |
private IRasterLayer m_DEM = null; |
41 |
private IRasterLayer m_Threshold = null; |
42 |
private IRasterLayer m_Network;
|
43 |
|
44 |
private ArrayList m_HeadersAndJunctions; |
45 |
|
46 |
|
47 |
@Override
|
48 |
public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
49 |
|
50 |
m_iMethod = m_Parameters.getParameterValueAsInt(METHOD); |
51 |
m_DEM = m_Parameters.getParameterValueAsRasterLayer(DEM); |
52 |
m_Threshold = m_Parameters.getParameterValueAsRasterLayer(THRESHOLDLAYER); |
53 |
m_dThreshold = m_Parameters.getParameterValueAsDouble(THRESHOLD); |
54 |
|
55 |
m_Network = getNewRasterLayer(NETWORK, Sextante.getText("Channel_network"), IRasterLayer.RASTER_DATA_TYPE_INT);
|
56 |
|
57 |
m_Network.assign(0.0);
|
58 |
|
59 |
final AnalysisExtent extent = m_Network.getWindowGridExtent();
|
60 |
m_DEM.setWindowExtent(extent); |
61 |
m_Threshold.setWindowExtent(extent); |
62 |
|
63 |
m_iNX = m_DEM.getNX(); |
64 |
m_iNY = m_DEM.getNY(); |
65 |
|
66 |
calculateChannelNetwork(); |
67 |
|
68 |
m_Network.setNoDataValue(0.0);
|
69 |
|
70 |
|
71 |
return !m_Task.isCanceled();
|
72 |
|
73 |
} |
74 |
|
75 |
|
76 |
@Override
|
77 |
public void defineCharacteristics() { |
78 |
|
79 |
final String sMethod[] = { Sextante.getText("Greater_than"), Sextante.getText("Lower_than") }; |
80 |
|
81 |
setName(Sextante.getText("Channel_network"));
|
82 |
setGroup(Sextante.getText("Basic_hydrological_analysis"));
|
83 |
setUserCanDefineAnalysisExtent(true);
|
84 |
|
85 |
try {
|
86 |
m_Parameters.addInputRasterLayer(DEM, Sextante.getText("Elevation"), true); |
87 |
m_Parameters.addInputRasterLayer(THRESHOLDLAYER, Sextante.getText("Threshold_layer"), true); |
88 |
m_Parameters.addSelection(METHOD, Sextante.getText("Criteria"), sMethod);
|
89 |
m_Parameters.addNumericalValue(THRESHOLD, Sextante.getText("Threshold"), 10000, |
90 |
AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE); |
91 |
addOutputRasterLayer(NETWORK, Sextante.getText("Channel_network"));
|
92 |
addOutputVectorLayer(NETWORKVECT, Sextante.getText("Channel_network"), OutputVectorLayer.SHAPE_TYPE_LINE);
|
93 |
} |
94 |
catch (final RepeatedParameterNameException e) { |
95 |
Sextante.addErrorToLog(e); |
96 |
} |
97 |
|
98 |
} |
99 |
|
100 |
|
101 |
private void calculateChannelNetwork() throws GeoAlgorithmExecutionException { |
102 |
|
103 |
int i;
|
104 |
final ArrayList alHeaders = getHeaders(); |
105 |
|
106 |
if (alHeaders != null) { |
107 |
m_HeadersAndJunctions = alHeaders; |
108 |
final Object[] headers = alHeaders.toArray(); |
109 |
Arrays.sort(headers);
|
110 |
|
111 |
setProgressText(Sextante.getText("Delineating_channel_network"));
|
112 |
if (headers.length > 0) { |
113 |
for (i = 0; (i < headers.length) && setProgress(i, headers.length); i++) { |
114 |
traceChannel((GridCell) headers[i]); |
115 |
} |
116 |
} |
117 |
|
118 |
if (!m_Task.isCanceled()) {
|
119 |
calculateOrderAndAddJunctions(); |
120 |
createVectorLayer(); |
121 |
} |
122 |
} |
123 |
|
124 |
} |
125 |
|
126 |
|
127 |
private ArrayList getHeaders() { |
128 |
|
129 |
int iDirection;
|
130 |
int x, y;
|
131 |
int ix, iy;
|
132 |
double dValue;
|
133 |
double dHeight1, dHeight2;
|
134 |
boolean bIsHeader;
|
135 |
final ArrayList headers = new ArrayList(); |
136 |
|
137 |
for (y = 0; (y < m_iNY) && setProgress(y, m_iNY); y++) { |
138 |
for (x = 0; x < m_iNX; x++) { |
139 |
dValue = m_Threshold.getCellValueAsDouble(x, y); |
140 |
dHeight1 = m_DEM.getCellValueAsDouble(x, y); |
141 |
if (meetsChannelConditions(dValue)) {
|
142 |
bIsHeader = true;
|
143 |
dHeight1 = m_DEM.getCellValueAsDouble(x, y); |
144 |
if (!m_DEM.isNoDataValue(dHeight1)) {
|
145 |
for (iDirection = 0; iDirection < 8; iDirection++) { |
146 |
ix = x + m_iOffsetX[iDirection]; |
147 |
iy = y + m_iOffsetY[iDirection]; |
148 |
dValue = m_Threshold.getCellValueAsDouble(ix, iy); |
149 |
if (meetsChannelConditions(dValue)) {
|
150 |
dHeight2 = m_DEM.getCellValueAsDouble(ix, iy); |
151 |
if (dHeight2 >= dHeight1) {
|
152 |
bIsHeader = false;
|
153 |
break;
|
154 |
} |
155 |
} |
156 |
} |
157 |
if (bIsHeader) {
|
158 |
headers.add(new GridCell(x, y, m_DEM.getCellValueAsDouble(x, y)));
|
159 |
} |
160 |
} |
161 |
} |
162 |
} |
163 |
} |
164 |
|
165 |
if (m_Task.isCanceled()) {
|
166 |
return null; |
167 |
} |
168 |
else {
|
169 |
return headers;
|
170 |
} |
171 |
|
172 |
} |
173 |
|
174 |
|
175 |
private boolean meetsChannelConditions(final double dValue) { |
176 |
|
177 |
if (m_iMethod == 0) { |
178 |
return (dValue > m_dThreshold);
|
179 |
} |
180 |
else if (m_iMethod == 1) { |
181 |
return (dValue < m_dThreshold);
|
182 |
} |
183 |
|
184 |
return false; |
185 |
|
186 |
} |
187 |
|
188 |
|
189 |
private void traceChannel(final GridCell cell) { |
190 |
|
191 |
int iDirection;
|
192 |
int x, y;
|
193 |
boolean bContinue = true; |
194 |
|
195 |
x = cell.getX(); |
196 |
y = cell.getY(); |
197 |
|
198 |
do {
|
199 |
m_Network.setCellValue(x, y, -1);
|
200 |
iDirection = m_DEM.getDirToNextDownslopeCell(x, y); |
201 |
if (iDirection >= 0) { |
202 |
x = x + m_iOffsetX[iDirection]; |
203 |
y = y + m_iOffsetY[iDirection]; |
204 |
} |
205 |
else {
|
206 |
bContinue = false;
|
207 |
} |
208 |
} |
209 |
while (bContinue && !m_Task.isCanceled());
|
210 |
|
211 |
} |
212 |
|
213 |
|
214 |
private void calculateOrderAndAddJunctions() { |
215 |
|
216 |
int x, y;
|
217 |
|
218 |
setProgressText(Sextante.getText("Calculating_orders"));
|
219 |
|
220 |
for (y = 0; (y < m_iNY) && setProgress(y, m_iNY); y++) { |
221 |
for (x = 0; x < m_iNX; x++) { |
222 |
getStrahlerOrder(x, y); |
223 |
} |
224 |
} |
225 |
|
226 |
} |
227 |
|
228 |
|
229 |
private int getStrahlerOrder(final int x, |
230 |
final int y) { |
231 |
|
232 |
int i;
|
233 |
int ix, iy;
|
234 |
int iDirection;
|
235 |
int iMaxOrder = 1; |
236 |
int iOrder = 1; |
237 |
int iMaxOrderCells = 0; |
238 |
int iUpslopeChannelCells = 0; |
239 |
|
240 |
if (m_Network.getCellValueAsInt(x, y) == -1) { |
241 |
; |
242 |
for (i = 0; i < 8; i++) { |
243 |
ix = x + m_iOffsetX[i]; |
244 |
iy = y + m_iOffsetY[i]; |
245 |
iDirection = m_DEM.getDirToNextDownslopeCell(ix, iy); |
246 |
if ((iDirection == (i + 4) % 8) && ((iOrder = m_Network.getCellValueAsInt(ix, iy)) != 0)) { |
247 |
iUpslopeChannelCells++; |
248 |
iOrder = m_Network.getCellValueAsInt(ix, iy); |
249 |
if (iOrder == -1) { |
250 |
iOrder = getStrahlerOrder(ix, iy); |
251 |
} |
252 |
if (iOrder > iMaxOrder) {
|
253 |
iMaxOrder = iOrder; |
254 |
iMaxOrderCells = 1;
|
255 |
} |
256 |
else if (iOrder == iMaxOrder) { |
257 |
iMaxOrderCells++; |
258 |
} |
259 |
} |
260 |
} |
261 |
|
262 |
if (iMaxOrderCells > 1) { |
263 |
iMaxOrder++; |
264 |
} |
265 |
|
266 |
if (iUpslopeChannelCells > 1) { |
267 |
m_HeadersAndJunctions.add(new GridCell(x, y, m_DEM.getCellValueAsDouble(x, y)));
|
268 |
} |
269 |
|
270 |
m_Network.setCellValue(x, y, iMaxOrder); |
271 |
|
272 |
} |
273 |
|
274 |
return iMaxOrder;
|
275 |
|
276 |
} |
277 |
|
278 |
|
279 |
private void createVectorLayer() throws GeoAlgorithmExecutionException { |
280 |
|
281 |
int i;
|
282 |
int x, y;
|
283 |
int ix, iy;
|
284 |
int iDirection;
|
285 |
int iIndexDownslope = -1; |
286 |
int iOrder;
|
287 |
boolean bContinue;
|
288 |
double dLength;
|
289 |
Point2D pt;
|
290 |
GridCell cell; |
291 |
ArrayList coordsList;
|
292 |
final AnalysisExtent extent = m_DEM.getWindowGridExtent();
|
293 |
final Object[] values = new Object[4]; |
294 |
|
295 |
final String sNames[] = { Sextante.getText("ID"), Sextante.getText("Length"), Sextante.getText("Order"), |
296 |
Sextante.getText("Next") };
|
297 |
final Class[] types = { Integer.class, Double.class, Integer.class, Integer.class }; |
298 |
|
299 |
final IVectorLayer network = getNewVectorLayer(NETWORKVECT, Sextante.getText("Channel_network"), |
300 |
IVectorLayer.SHAPE_TYPE_LINE, types, sNames); |
301 |
final Object[] headers = m_HeadersAndJunctions.toArray(); |
302 |
Arrays.sort(headers);
|
303 |
|
304 |
setProgressText(Sextante.getText("Creating_vector_layer"));
|
305 |
for (i = headers.length - 1; (i > -1) && setProgress(headers.length - i, headers.length); i--) { |
306 |
cell = (GridCell) headers[i]; |
307 |
x = cell.getX(); |
308 |
y = cell.getY(); |
309 |
coordsList = new ArrayList(); |
310 |
pt = extent.getWorldCoordsFromGridCoords(cell); |
311 |
coordsList.add(new Coordinate(pt.getX(), pt.getY()));
|
312 |
dLength = 0;
|
313 |
iOrder = m_Network.getCellValueAsInt(x, y); |
314 |
bContinue = true;
|
315 |
do {
|
316 |
iDirection = m_DEM.getDirToNextDownslopeCell(x, y); |
317 |
if (iDirection >= 0) { |
318 |
ix = x + m_iOffsetX[iDirection]; |
319 |
iy = y + m_iOffsetY[iDirection]; |
320 |
cell = new GridCell(ix, iy, m_DEM.getCellValueAsDouble(ix, iy));
|
321 |
pt = extent.getWorldCoordsFromGridCoords(cell); |
322 |
coordsList.add(new Coordinate(pt.getX(), pt.getY()));
|
323 |
dLength += m_DEM.getDistToNeighborInDir(iDirection); |
324 |
iIndexDownslope = m_HeadersAndJunctions.indexOf(cell); |
325 |
if (iIndexDownslope != -1) { |
326 |
bContinue = false;
|
327 |
} |
328 |
x = ix; |
329 |
y = iy; |
330 |
} |
331 |
else {
|
332 |
bContinue = false;
|
333 |
} |
334 |
|
335 |
} |
336 |
while (bContinue && !m_Task.isCanceled());
|
337 |
|
338 |
values[0] = new Integer(i); |
339 |
values[1] = new Double(dLength); |
340 |
values[2] = new Integer(iOrder); |
341 |
values[3] = new Integer(iIndexDownslope); |
342 |
|
343 |
final Coordinate coords[] = new Coordinate[coordsList.size()]; |
344 |
for (int j = 0; j < coords.length; j++) { |
345 |
coords[j] = (Coordinate) coordsList.get(j); |
346 |
} |
347 |
final Geometry geom = new GeometryFactory().createLineString(coords); |
348 |
network.addFeature(geom, values); |
349 |
} |
350 |
} |
351 |
} |