Statistics
| Revision:

root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / vectorize / contourLines / ContourLinesAlgorithm.java @ 59

History | View | Annotate | Download (11.3 KB)

1
package es.unex.sextante.vectorize.contourLines;
2

    
3
import java.util.ArrayList;
4

    
5
import com.vividsolutions.jts.geom.Coordinate;
6
import com.vividsolutions.jts.geom.Geometry;
7
import com.vividsolutions.jts.geom.GeometryFactory;
8

    
9
import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue;
10
import es.unex.sextante.core.GeoAlgorithm;
11
import es.unex.sextante.core.Sextante;
12
import es.unex.sextante.dataObjects.IRasterLayer;
13
import es.unex.sextante.dataObjects.IVectorLayer;
14
import es.unex.sextante.exceptions.RepeatedParameterNameException;
15
import es.unex.sextante.outputs.OutputVectorLayer;
16

    
17
public class ContourLinesAlgorithm
18
         extends
19
            GeoAlgorithm {
20

    
21
   public static final String    LAYER    = "LAYER";
22
   public static final String    DISTANCE = "DISTANCE";
23
   public static final String    MIN      = "MIN";
24
   public static final String    MAX      = "MAX";
25
   public static final String    RESULT   = "RESULT";
26

    
27
   private IRasterLayer          m_Window;
28
   private IVectorLayer          m_Contour;
29
   private char[][]              m_Row;
30
   private char[][]              m_Col;
31
   private final GeometryFactory m_GF     = new GeometryFactory();
32

    
33

    
34
   @Override
35
   public void defineCharacteristics() {
36

    
37
      setName(Sextante.getText("Contour_lines"));
38
      setGroup(Sextante.getText("Vectorization"));
39
      setUserCanDefineAnalysisExtent(false);
40

    
41
      try {
42
         m_Parameters.addInputRasterLayer(LAYER, Sextante.getText("Input_layer"), true);
43
         m_Parameters.addNumericalValue(DISTANCE, Sextante.getText("Equidistance"),
44
                  AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE, 100, 0, Double.MAX_VALUE);
45
         m_Parameters.addNumericalValue(MIN, Sextante.getText("Min_value"), 0,
46
                  AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE);
47
         m_Parameters.addNumericalValue(MAX, Sextante.getText("Max_value"), 10000.,
48
                  AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE);
49
         addOutputVectorLayer(RESULT, Sextante.getText("Contour_lines"), OutputVectorLayer.SHAPE_TYPE_LINE);
50
      }
51
      catch (final RepeatedParameterNameException e) {
52
         Sextante.addErrorToLog(e);
53
      }
54

    
55
   }
56

    
57

    
58
   @Override
59
   public boolean processAlgorithm() {
60

    
61
      double dMin, dMax;
62
      double dDistance;
63
      final String sFields[] = new String[2];
64
      final Class types[] = { Integer.class, Double.class };
65

    
66
      try {
67

    
68
         m_Window = m_Parameters.getParameterValueAsRasterLayer(LAYER);
69
         dMin = m_Parameters.getParameterValueAsDouble(MIN);
70
         dMax = m_Parameters.getParameterValueAsDouble(MAX);
71
         dDistance = m_Parameters.getParameterValueAsDouble(DISTANCE);
72

    
73
         m_Window.setFullExtent();
74

    
75
         if ((dMin <= dMax) && (dDistance > 0)) {
76
            if (dMin < m_Window.getMinValue()) {
77
               dMin += dDistance * (int) ((m_Window.getMinValue() - dMin) / dDistance);
78
            }
79
            if (dMax > m_Window.getMaxValue()) {
80
               dMax = m_Window.getMaxValue();
81
            }
82

    
83
            sFields[0] = "ID";
84
            sFields[1] = "Elevation";
85

    
86
            m_Contour = getNewVectorLayer(RESULT, Sextante.getText("Contour_lines"), IVectorLayer.SHAPE_TYPE_LINE, types, sFields);
87

    
88
            createContours(dMin, dMax, dDistance);
89

    
90
            return !m_Task.isCanceled();
91
         }
92

    
93
         return false;
94

    
95
      }
96
      catch (final Exception e) {
97
         Sextante.addErrorToLog(e);
98
         return false;
99
      }
100

    
101
   }
102

    
103

    
104
   private void createContours(final double dMin,
105
                               final double dMax,
106
                               double dDistance) {
107

    
108
      int x, y;
109
      int i;
110
      int ID;
111
      int iNX, iNY;
112
      double dZ;
113
      double dValue = 0;
114

    
115
      iNX = m_Window.getNX();
116
      iNY = m_Window.getNY();
117

    
118
      m_Row = new char[iNY][iNX];
119
      m_Col = new char[iNY][iNX];
120

    
121
      if (dDistance <= 0) {
122
         dDistance = 1;
123
      }
124

    
125
      for (dZ = dMin, ID = 0; (dZ <= dMax) && setProgress((int) (dZ - dMin), (int) (dMax - dMin)); dZ += dDistance) {
126
         for (y = 0; y < iNY - 1; y++) {
127
            for (x = 0; x < iNX - 1; x++) {
128
               dValue = m_Window.getCellValueAsDouble(x, y);
129
               if (dValue >= dZ) {
130
                  m_Row[y][x] = (char) (m_Window.getCellValueAsDouble(x + 1, y) < dZ ? 1 : 0);
131
                  m_Col[y][x] = (char) (m_Window.getCellValueAsDouble(x, y + 1) < dZ ? 1 : 0);
132
               }
133
               else {
134
                  m_Row[y][x] = (char) (m_Window.getCellValueAsDouble(x + 1, y) >= dZ ? 1 : 0);
135
                  m_Col[y][x] = (char) (m_Window.getCellValueAsDouble(x, y + 1) >= dZ ? 1 : 0);
136
               }
137
            }
138
         }
139

    
140
         for (y = 0; y < iNY - 1; y++) {
141
            for (x = 0; x < iNX - 1; x++) {
142
               if (m_Row[y][x] != 0) {
143
                  for (i = 0; i < 2; i++) {
144
                     findContour(x, y, dZ, true, ID++);
145
                  }
146
                  m_Row[y][x] = 0;
147
               }
148

    
149
               if (m_Col[y][x] != 0) {
150
                  for (i = 0; i < 2; i++) {
151
                     findContour(x, y, dZ, false, ID++);
152
                  }
153
                  m_Col[y][x] = 0;
154
               }
155
            }
156
         }
157

    
158
      }
159

    
160
   }
161

    
162

    
163
   private void findContour(final int x,
164
                            final int y,
165
                            final double z,
166
                            final boolean doRow,
167
                            final int ID) {
168

    
169
      boolean doContinue = true;
170
      final boolean bIsFirstPoint = true;
171
      int zx = doRow ? x + 1 : x;
172
      int zy = doRow ? y : y + 1;
173
      double d;
174
      double xPos, yPos;
175
      final double xMin = m_Window.getWindowGridExtent().getXMin();
176
      final double yMax = m_Window.getWindowGridExtent().getYMax();
177
      Geometry line;
178
      final Object values[] = new Object[2];
179
      final NextContourInfo info = new NextContourInfo();
180
      final ArrayList<Coordinate> coords = new ArrayList<Coordinate>();
181

    
182
      info.x = x;
183
      info.y = y;
184
      info.iDir = 0;
185
      info.doRow = doRow;
186

    
187
      do {
188

    
189
         d = m_Window.getCellValueAsDouble(info.x, info.y);
190
         d = (d - z) / (d - m_Window.getCellValueAsDouble(zx, zy));
191

    
192
         xPos = xMin + m_Window.getWindowCellSize() * (info.x + d * (zx - info.x) + 0.5);
193
         yPos = yMax - m_Window.getWindowCellSize() * (info.y + d * (zy - info.y) + 0.5);
194

    
195
         coords.add(new Coordinate(xPos, yPos));
196

    
197
         if (!findNextContour(info)) {
198
            doContinue = findNextContour(info);
199
         }
200

    
201
         info.iDir = (info.iDir + 5) % 8;
202

    
203
         if (info.doRow) {
204
            m_Row[info.y][info.x] = 0;
205
            zx = info.x + 1;
206
            zy = info.y;
207
         }
208
         else {
209
            m_Col[info.y][info.x] = 0;
210
            zx = info.x;
211
            zy = info.y + 1;
212
         }
213

    
214
      }
215
      while (doContinue);
216

    
217
      values[0] = new Integer(ID);
218
      values[1] = new Double(z);
219

    
220
      final Coordinate[] coordinates = new Coordinate[coords.size()];
221
      for (int i = 0; i < coordinates.length; i++) {
222
         coordinates[i] = coords.get(i);
223
      }
224

    
225
      if (coordinates.length > 1) {
226
         line = m_GF.createLineString(coordinates);
227
         m_Contour.addFeature(line, values);
228
      }
229

    
230
   }
231

    
232

    
233
   private boolean findNextContour(final NextContourInfo info) {
234

    
235
      boolean doContinue;
236

    
237
      if (info.doRow) {
238
         switch (info.iDir) {
239
            case 0:
240
               if (m_Row[info.y + 1][info.x] != 0) {
241
                  info.y++;
242
                  info.iDir = 0;
243
                  doContinue = true;
244
                  break;
245
               }
246
            case 1:
247
               if (m_Col[info.y][info.x + 1] != 0) {
248
                  info.x++;
249
                  info.iDir = 1;
250
                  info.doRow = false;
251
                  doContinue = true;
252
                  break;
253
               }
254
            case 2:
255
            case 3:
256
               if (info.y - 1 >= 0) {
257
                  if (m_Col[info.y - 1][info.x + 1] != 0) {
258
                     info.x++;
259
                     info.y--;
260
                     info.doRow = false;
261
                     info.iDir = 3;
262
                     doContinue = true;
263
                     break;
264
                  }
265
               }
266
            case 4:
267
               if (info.y - 1 >= 0) {
268
                  if (m_Row[info.y - 1][info.x] != 0) {
269
                     info.y--;
270
                     info.iDir = 4;
271
                     doContinue = true;
272
                     break;
273
                  }
274
               }
275
            case 5:
276
               if (info.y - 1 >= 0) {
277
                  if (m_Col[info.y - 1][info.x] != 0) {
278
                     info.y--;
279
                     info.doRow = false;
280
                     info.iDir = 5;
281
                     doContinue = true;
282
                     break;
283
                  }
284
               }
285
            case 6:
286
            case 7:
287
               if (m_Col[info.y][info.x] != 0) {
288
                  info.doRow = false;
289
                  info.iDir = 7;
290
                  doContinue = true;
291
                  break;
292
               }
293
            default:
294
               info.iDir = 0;
295
               doContinue = false;
296
         }
297
      }
298
      else {
299
         switch (info.iDir) {
300
            case 0:
301
            case 1:
302
               if (m_Row[info.y + 1][info.x] != 0) {
303
                  info.y++;
304
                  info.doRow = true;
305
                  info.iDir = 1;
306
                  doContinue = true;
307
                  break;
308
               }
309
            case 2:
310
               if (m_Col[info.y][info.x + 1] != 0) {
311
                  info.x++;
312
                  info.iDir = 2;
313
                  doContinue = true;
314
                  break;
315
               }
316
            case 3:
317
               if (m_Row[info.y][info.x] != 0) {
318
                  info.doRow = true;
319
                  info.iDir = 3;
320
                  doContinue = true;
321
                  break;
322
               }
323
            case 4:
324
            case 5:
325
               if (info.x - 1 >= 0) {
326
                  if (m_Row[info.y][info.x - 1] != 0) {
327
                     info.x--;
328
                     info.doRow = true;
329
                     info.iDir = 5;
330
                     doContinue = true;
331
                     break;
332
                  }
333
               }
334
            case 6:
335
               if (info.x - 1 >= 0) {
336
                  if (m_Col[info.y][info.x - 1] != 0) {
337
                     info.x--;
338
                     info.iDir = 6;
339
                     doContinue = true;
340
                     break;
341
                  }
342
               }
343
            case 7:
344
               if (info.x - 1 >= 0) {
345
                  if (m_Row[info.y + 1][info.x - 1] != 0) {
346
                     info.x--;
347
                     info.y++;
348
                     info.doRow = true;
349
                     info.iDir = 7;
350
                     doContinue = true;
351
                     break;
352
                  }
353
               }
354
            default:
355
               info.iDir = 0;
356
               doContinue = false;
357
         }
358
      }
359

    
360
      return (doContinue);
361
   }
362

    
363
   private class NextContourInfo {
364

    
365
      public int     iDir;
366
      public int     x;
367
      public int     y;
368
      public boolean doRow;
369

    
370
   }
371

    
372
}