Statistics
| Revision:

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
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
}