root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / hydrology / watersheds / WatershedsAlgorithm.java @ 59
History | View | Annotate | Download (7.32 KB)
1 | 59 | nbrodin | package es.unex.sextante.hydrology.watersheds; |
---|---|---|---|
2 | |||
3 | import java.util.ArrayList; |
||
4 | import java.util.Arrays; |
||
5 | |||
6 | import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue; |
||
7 | import es.unex.sextante.core.GeoAlgorithm; |
||
8 | import es.unex.sextante.core.AnalysisExtent; |
||
9 | import es.unex.sextante.core.Sextante; |
||
10 | import es.unex.sextante.dataObjects.IRasterLayer; |
||
11 | import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
||
12 | import es.unex.sextante.exceptions.RepeatedParameterNameException; |
||
13 | import es.unex.sextante.rasterWrappers.GridCell; |
||
14 | |||
15 | public class WatershedsAlgorithm |
||
16 | extends
|
||
17 | GeoAlgorithm { |
||
18 | |||
19 | private static final int NO_BASIN = -1; |
||
20 | private final static int m_iOffsetX[] = { 0, 1, 1, 1, 0, -1, -1, -1 }; |
||
21 | private final static int m_iOffsetY[] = { 1, 1, 0, -1, -1, -1, 0, 1 }; |
||
22 | |||
23 | public static final String DEM = "DEM"; |
||
24 | public static final String NETWORK = "NETWORK"; |
||
25 | public static final String MINSIZE = "MINSIZE"; |
||
26 | public static final String WATERSHEDS = "WATERSHEDS"; |
||
27 | |||
28 | private int m_iBasins; |
||
29 | private int m_iNX, m_iNY; |
||
30 | private int m_iMinSize; |
||
31 | |||
32 | private IRasterLayer m_DEM = null; |
||
33 | private IRasterLayer m_Network = null; |
||
34 | private IRasterLayer m_Basins;
|
||
35 | private IRasterLayer m_Directions;
|
||
36 | |||
37 | |||
38 | @Override
|
||
39 | public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
||
40 | |||
41 | m_DEM = m_Parameters.getParameterValueAsRasterLayer(DEM); |
||
42 | m_Network = m_Parameters.getParameterValueAsRasterLayer(NETWORK); |
||
43 | m_iMinSize = m_Parameters.getParameterValueAsInt(MINSIZE); |
||
44 | |||
45 | m_Basins = getNewRasterLayer(WATERSHEDS, Sextante.getText("Watersheds"), IRasterLayer.RASTER_DATA_TYPE_INT);
|
||
46 | |||
47 | m_Basins.setNoDataValue(NO_BASIN); |
||
48 | m_Basins.assignNoData(); |
||
49 | |||
50 | final AnalysisExtent extent = m_Basins.getWindowGridExtent();
|
||
51 | m_DEM.setFullExtent(); |
||
52 | m_Network.setWindowExtent(extent); |
||
53 | |||
54 | m_Directions = getTempRasterLayer(IRasterLayer.RASTER_DATA_TYPE_INT, extent); |
||
55 | |||
56 | m_iNX = m_DEM.getNX(); |
||
57 | m_iNY = m_DEM.getNY(); |
||
58 | |||
59 | calculateBasins(); |
||
60 | |||
61 | return !m_Task.isCanceled();
|
||
62 | |||
63 | } |
||
64 | |||
65 | |||
66 | @Override
|
||
67 | public void defineCharacteristics() { |
||
68 | |||
69 | setName(Sextante.getText("Watersheds"));
|
||
70 | setGroup(Sextante.getText("Basic_hydrological_analysis"));
|
||
71 | setUserCanDefineAnalysisExtent(true);
|
||
72 | |||
73 | try {
|
||
74 | m_Parameters.addInputRasterLayer(DEM, Sextante.getText("Elevation"), true); |
||
75 | m_Parameters.addInputRasterLayer(NETWORK, Sextante.getText("Channel_network"), true); |
||
76 | m_Parameters.addNumericalValue(MINSIZE, Sextante.getText("Minimum_watershed_size__cells"), 0, |
||
77 | AdditionalInfoNumericalValue.NUMERICAL_VALUE_INTEGER); |
||
78 | addOutputRasterLayer(WATERSHEDS, Sextante.getText("Watersheds"));
|
||
79 | } |
||
80 | catch (final RepeatedParameterNameException e) { |
||
81 | Sextante.addErrorToLog(e); |
||
82 | } |
||
83 | |||
84 | } |
||
85 | |||
86 | |||
87 | private void calculateBasins() { |
||
88 | |||
89 | int i;
|
||
90 | int x, y;
|
||
91 | int iBasins;
|
||
92 | prepareDirectionsLayer(); |
||
93 | final ArrayList outletsArrayList = getOutlets(); |
||
94 | final Object[] outlets = outletsArrayList.toArray(); |
||
95 | Arrays.sort(outlets);
|
||
96 | |||
97 | m_iBasins = 0;
|
||
98 | for (i = outlets.length - 1; (i >= 0) && setProgress(outlets.length - i, outlets.length); i--) { |
||
99 | m_iBasins++; |
||
100 | x = ((GridCell) outlets[i]).getX(); |
||
101 | y = ((GridCell) outlets[i]).getY(); |
||
102 | if (getBasin(x, y) < m_iMinSize) {
|
||
103 | iBasins = m_iBasins - 1;
|
||
104 | m_iBasins = NO_BASIN; |
||
105 | getBasin(x, y); |
||
106 | m_iBasins = iBasins; |
||
107 | } |
||
108 | } |
||
109 | |||
110 | } |
||
111 | |||
112 | |||
113 | private void prepareDirectionsLayer() { |
||
114 | |||
115 | int x, y;
|
||
116 | int iDir;
|
||
117 | |||
118 | for (y = 0; (y < m_iNY) && setProgress(y, m_iNY); y++) { |
||
119 | for (x = 0; x < m_iNX; x++) { |
||
120 | iDir = m_DEM.getDirToNextDownslopeCell(x, y, false);
|
||
121 | if (iDir < 0) { |
||
122 | m_Directions.setCellValue(x, y, -1.0);
|
||
123 | } |
||
124 | else {
|
||
125 | m_Directions.setCellValue(x, y, ((iDir + 4) % 8)); |
||
126 | } |
||
127 | } |
||
128 | } |
||
129 | |||
130 | } |
||
131 | |||
132 | |||
133 | private ArrayList getOutlets() { |
||
134 | |||
135 | int x, y;
|
||
136 | final ArrayList outlets = new ArrayList(); |
||
137 | |||
138 | for (y = 0; (y < m_iNY) && setProgress(y, m_iNY); y++) { |
||
139 | for (x = 0; x < m_iNX; x++) { |
||
140 | addOutlet(x, y, outlets); |
||
141 | } |
||
142 | |||
143 | } |
||
144 | |||
145 | return outlets;
|
||
146 | |||
147 | } |
||
148 | |||
149 | |||
150 | private void addOutlet(final int x, |
||
151 | final int y, |
||
152 | final ArrayList outlets) { |
||
153 | |||
154 | int i;
|
||
155 | int ix, iy;
|
||
156 | int iUpslopeX = 0, iUpslopeY = 0; |
||
157 | int iUpslopeRiverCells = 0; |
||
158 | double dUpslopeZ = 0; |
||
159 | int iNetwork = m_Network.getCellValueAsInt(x, y);
|
||
160 | final int iDir = m_Directions.getCellValueAsInt(x, y); |
||
161 | final double dZ = m_DEM.getCellValueAsDouble(x, y); |
||
162 | final int iNextCellX = x + m_iOffsetX[(iDir + 4) % 8]; |
||
163 | final int iNextCellY = y + m_iOffsetY[(iDir + 4) % 8]; |
||
164 | final int iNextCellNetwork = m_Network.getCellValueAsInt(iNextCellX, iNextCellY); |
||
165 | |||
166 | if (m_Network.isNoDataValue(iNetwork) || (iNetwork == 0)) { //not a river cell |
||
167 | return;
|
||
168 | } |
||
169 | if (m_Network.isNoDataValue(iNextCellNetwork) || (iNextCellNetwork == 0)) { //border river cell |
||
170 | outlets.add(new GridCell(x, y, dZ));
|
||
171 | } |
||
172 | else if (iNetwork < 0) { // user defined outlet |
||
173 | outlets.add(new GridCell(x, y, dZ));
|
||
174 | return;
|
||
175 | } |
||
176 | else if ((iDir == -1) && !m_DEM.isNoDataValue(dZ)) { //border cell, limits with no data or with grid boundaries |
||
177 | outlets.add(new GridCell(x, y, dZ));
|
||
178 | } |
||
179 | else {
|
||
180 | for (i = 0; i < 8; i++) { |
||
181 | ix = x + m_iOffsetX[i]; |
||
182 | iy = y + m_iOffsetY[i]; |
||
183 | if (m_Directions.getCellValueAsInt(ix, iy) == i) {
|
||
184 | iNetwork = m_Network.getCellValueAsInt(ix, iy); |
||
185 | if ((iNetwork > 0) && !m_Network.isNoDataValue(iNetwork)) { |
||
186 | if (iUpslopeRiverCells > 0) { |
||
187 | if (iUpslopeRiverCells == 1) { |
||
188 | outlets.add(new GridCell(iUpslopeX, iUpslopeY, dUpslopeZ));
|
||
189 | } |
||
190 | outlets.add(new GridCell(ix, iy, m_DEM.getCellValueAsDouble(ix, iy)));
|
||
191 | } |
||
192 | else {
|
||
193 | iUpslopeX = ix; |
||
194 | iUpslopeY = iy; |
||
195 | dUpslopeZ = m_DEM.getCellValueAsDouble(x, y); |
||
196 | } |
||
197 | iUpslopeRiverCells++; |
||
198 | } |
||
199 | } |
||
200 | } |
||
201 | } |
||
202 | |||
203 | } |
||
204 | |||
205 | |||
206 | private int getBasin(final int x, |
||
207 | final int y) { |
||
208 | |||
209 | int i, ix, iy, nCells = 1; |
||
210 | |||
211 | final int iBasin = m_Basins.getCellValueAsInt(x, y); |
||
212 | final int iDir = m_Directions.getCellValueAsInt(x, y); |
||
213 | if ((iBasin == NO_BASIN) && !m_Directions.isNoDataValue(iDir)) {
|
||
214 | |||
215 | m_Basins.setCellValue(x, y, m_iBasins); |
||
216 | |||
217 | for (i = 0, nCells = 1; i < 8; i++) { |
||
218 | ix = x + m_iOffsetX[i]; |
||
219 | iy = y + m_iOffsetY[i]; |
||
220 | if ((m_Directions.getCellValueAsInt(ix, iy) == i) && (m_Basins.getCellValueAsInt(ix, iy) == NO_BASIN)) {
|
||
221 | nCells += getBasin(ix, iy); |
||
222 | } |
||
223 | } |
||
224 | return nCells;
|
||
225 | } |
||
226 | |||
227 | return 0; |
||
228 | } |
||
229 | |||
230 | } |