Statistics
| Revision:

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

History | View | Annotate | Download (18.5 KB)

1
//package es.unex.sextante.vectorize.vectorize;
2
//
3
//import java.awt.geom.Point2D;
4
//import java.util.ArrayList;
5
//
6
//import com.vividsolutions.jts.geom.Coordinate;
7
//import com.vividsolutions.jts.geom.Geometry;
8
//import com.vividsolutions.jts.geom.GeometryFactory;
9
//import com.vividsolutions.jts.geom.LinearRing;
10
//import com.vividsolutions.jts.geom.Polygon;
11
//
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.exceptions.UnsupportedOutputChannelException;
20
//import es.unex.sextante.outputs.OutputVectorLayer;
21
//
22
//public class VectorizeAlgorithm
23
//         extends
24
//            GeoAlgorithm {
25
//
26
//   public static final String    LAYER  = "LAYER";
27
//   public static final String    RESULT = "RESULT";
28
//
29
//   private IRasterLayer          m_Input;
30
//   private IRasterLayer          m_Edge;
31
//   private IVectorLayer          m_Polygons;
32
//   private int                   m_iNX, m_iNY;
33
//   private char[][]              m_Lock;
34
//   private ArrayList<Coordinate> m_Coords;
35
//   private ArrayList<Geometry>   m_Polyg;
36
//
37
//   private static final int      m_IX[] = { 0, 1, 1, 1, 0, -1, -1, -1 };
38
//   private static final int      m_IY[] = { -1, -1, 0, 1, 1, 1, 0, -1 };
39
//
40
//
41
//   @Override
42
//   public void defineCharacteristics() {
43
//
44
//      setName(Sextante.getText("Vectorize_raster_layer__polygons"));
45
//      setGroup(Sextante.getText("Vectorization"));
46
//      setUserCanDefineAnalysisExtent(true);
47
//
48
//      try {
49
//         m_Parameters.addInputRasterLayer(LAYER, Sextante.getText("Input_layer"), true);
50
//         addOutputVectorLayer(RESULT, Sextante.getText("Result"), OutputVectorLayer.SHAPE_TYPE_POLYGON);
51
//      }
52
//      catch (final RepeatedParameterNameException e) {
53
//         Sextante.addErrorToLog(e);
54
//      }
55
//
56
//   }
57
//
58
//
59
//   @Override
60
//   public boolean processAlgorithm() throws GeoAlgorithmExecutionException {
61
//
62
//      final String sFields[] = new String[2];
63
//      final Class types[] = { Integer.class, Double.class };
64
//
65
//      m_Input = m_Parameters.getParameterValueAsRasterLayer(LAYER);
66
//      m_Input.setWindowExtent(m_AnalysisExtent);
67
//
68
//      sFields[0] = "ID";
69
//      sFields[1] = m_Input.getName();
70
//
71
//      m_Polygons = getNewVectorLayer(RESULT, Sextante.getText("Result"), IVectorLayer.SHAPE_TYPE_POLYGON, types, sFields);
72
//
73
//      createPolygons();
74
//
75
//      return !m_Task.isCanceled();
76
//
77
//   }
78
//
79
//
80
//   private void createPolygons() throws UnsupportedOutputChannelException {
81
//
82
//      int x, y, ID;
83
//      double dValue;
84
//
85
//      m_iNX = m_Input.getNX();
86
//      m_iNY = m_Input.getNY();
87
//
88
//      m_Coords = new ArrayList<Coordinate>();
89
//      m_Polyg = new ArrayList<Geometry>();
90
//
91
//      m_Lock = new char[m_iNY][m_iNX];
92
//
93
//      final AnalysisExtent ge = new AnalysisExtent();
94
//      final AnalysisExtent wge = m_Input.getWindowGridExtent();
95
//      ge.setCellSize(wge.getCellSize() * .5);
96
//      ge.setXRange(wge.getXMin() - wge.getCellSize() * .5, wge.getXMax() + wge.getCellSize() * .5, true);
97
//      ge.setYRange(wge.getYMin() - wge.getCellSize() * .5, wge.getYMax() + wge.getCellSize() * .5, true);
98
//      m_Edge = getTempRasterLayer(IRasterLayer.RASTER_DATA_TYPE_BYTE, ge);
99
//
100
//      //m_Area = new char[m_iNY + 1][m_iNX + 1];
101
//
102
//      for (y = 0, ID = 1; (y < m_iNY) && setProgress(y, m_iNY); y++) {
103
//         for (x = 0; x < m_iNX; x++) {
104
//            dValue = m_Input.getCellValueAsDouble(x, y);
105
//            if (!m_Input.isNoDataValue(dValue) && (m_Lock[y][x] == 0)) {
106
//               Get_Class(dValue);
107
//               final Object values[] = new Object[2];
108
//               values[0] = new Integer(ID++);
109
//               values[1] = new Double(dValue);
110
//               final GeometryFactory gf = new GeometryFactory();
111
//               m_Polygons.addFeature(gf.createMultiPolygon(m_Polyg.toArray(new Polygon[0])), values);
112
//            }
113
//         }
114
//      }
115
//
116
//   }
117
//
118
//
119
//   private void Get_Class(final double dClassValue) {
120
//
121
//      int x, y, i, ix, iy, n, nEdgeCells;
122
//
123
//      m_Polyg.clear();
124
//
125
//      for (y = 0, nEdgeCells = 0; (y < m_iNY) && !this.m_Task.isCanceled(); y++) {
126
//         for (x = 0; x < m_iNX; x++) {
127
//            double dValue = m_Input.getCellValueAsDouble(x, y);
128
//            if ((m_Lock[y][x] == 0) && (dValue == dClassValue)) {
129
//               m_Lock[y][x] = 1;
130
//               for (i = 0, n = 0; i < 8; i += 2) {
131
//                  ix = Get_xTo(i, x);
132
//                  iy = Get_yTo(i, y);
133
//                  dValue = m_Input.getCellValueAsDouble(ix, iy);
134
//                  if (dValue != dClassValue) {
135
//                     ix = Get_xTo(i, 1 + 2 * x);
136
//                     iy = Get_yTo(i, 1 + 2 * y);
137
//                     m_Edge.setCellValue(ix, iy, i + 2);
138
//
139
//                     ix = Get_xTo(i - 1, 1 + 2 * x);
140
//                     iy = Get_yTo(i - 1, 1 + 2 * y);
141
//                     m_Edge.setCellValue(ix, iy, m_Edge.getCellValueAsInt(ix, iy) != 0 ? -1 : i + 2);
142
//
143
//                     n++;
144
//                  }
145
//               }
146
//
147
//               if (n == 4) {
148
//                  Get_Square(1 + 2 * x, 1 + 2 * y);
149
//               }
150
//               else {
151
//                  nEdgeCells++;
152
//               }
153
//            }
154
//         }
155
//      }
156
//
157
//      if (nEdgeCells > 0) {
158
//         Get_Polygons();
159
//      }
160
//
161
//   }
162
//
163
//
164
//   private void Get_Square(final int x,
165
//                           final int y) {
166
//
167
//      int i, ix, iy;
168
//      final double dCellSize = m_Edge.getWindowCellSize() * .5;
169
//
170
//      for (i = 0; i < 8; i++) {
171
//         ix = Get_xTo(i, x);
172
//         iy = Get_yTo(i, y);
173
//
174
//         m_Edge.setCellValue(ix, iy, m_Edge.getCellValueAsInt(ix, iy) > 0 ? 0 : (i > 1 ? i - 1 : i + 7));
175
//
176
//         if (i % 2 != 0) {
177
//            Point2D pt;
178
//            pt = m_Edge.getWindowGridExtent().getWorldCoordsFromGridCoords(ix, iy);
179
//            m_Coords.add(new Coordinate(pt.getX() + dCellSize, pt.getY() - dCellSize));
180
//         }
181
//      }
182
//   }
183
//
184
//
185
//   private void Get_Polygons() {
186
//
187
//      for (int y = 0; (y < m_Edge.getNY()) && !m_Task.isCanceled(); y++) {
188
//         for (int x = 0; x < m_Edge.getNX(); x++) {
189
//            if (m_Edge.getCellValueAsInt(x, y) > 0) {
190
//               m_Coords.clear();
191
//               Get_Polygon(x, y);
192
//               final Coordinate coord = m_Coords.get(0);
193
//               m_Coords.add(new Coordinate(coord.x, coord.y));
194
//               final Coordinate[] coords = m_Coords.toArray(new Coordinate[0]);
195
//               final GeometryFactory gf = new GeometryFactory();
196
//               try {
197
//                  final LinearRing ring = gf.createLinearRing(coords);
198
//                  m_Polyg.add(gf.createPolygon(ring, null));
199
//               }
200
//               catch (final Exception e) {
201
//                  // might reach this if we try to create a polygon with less than 3 coords.
202
//                  // we just ignore it
203
//               }
204
//            }
205
//         }
206
//      }
207
//
208
//   }
209
//
210
//
211
//   private void Get_Polygon(int x,
212
//                            int y) {
213
//
214
//      int i, iLast = -1;
215
//      final double dCellSize = m_Edge.getWindowCellSize() * .5;
216
//
217
//      while ((i = m_Edge.getCellValueAsInt(x, y)) != 0) {
218
//         if (i < 0) {
219
//            i = iLast + 2;
220
//            m_Edge.setCellValue(x, y, (iLast == 2 ? 8 : iLast - 2));
221
//         }
222
//         else {
223
//            m_Edge.setCellValue(x, y, 0);
224
//         }
225
//
226
//         if (i != iLast) {
227
//            final Point2D pt = m_Edge.getWindowGridExtent().getWorldCoordsFromGridCoords(x, y);
228
//            iLast = i;
229
//            m_Coords.add(new Coordinate(pt.getX() + dCellSize, pt.getY() - dCellSize));
230
//         }
231
//
232
//         x = Get_xTo(i, x);
233
//         y = Get_yTo(i, y);
234
//      }
235
//   }
236
//
237
//
238
//   private int Get_xTo(int Direction,
239
//                       final int x) {
240
//
241
//      Direction %= 8;
242
//
243
//      if (Direction < 0) {
244
//         Direction += 8;
245
//      }
246
//
247
//      return (x + m_IX[Direction]);
248
//
249
//   }
250
//
251
//
252
//   private int Get_yTo(int Direction,
253
//                       final int x) {
254
//
255
//      Direction %= 8;
256
//
257
//      if (Direction < 0) {
258
//         Direction += 8;
259
//      }
260
//
261
//      return (x + m_IY[Direction]);
262
//
263
//   }
264
//
265
//
266
//}
267

    
268
package es.unex.sextante.vectorize.vectorize;
269

    
270
import java.util.ArrayList;
271

    
272
import com.vividsolutions.jts.geom.Coordinate;
273
import com.vividsolutions.jts.geom.GeometryFactory;
274
import com.vividsolutions.jts.geom.LinearRing;
275
import com.vividsolutions.jts.geom.Polygon;
276

    
277
import es.unex.sextante.core.GeoAlgorithm;
278
import es.unex.sextante.core.Sextante;
279
import es.unex.sextante.dataObjects.IRasterLayer;
280
import es.unex.sextante.dataObjects.IVectorLayer;
281
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException;
282
import es.unex.sextante.exceptions.RepeatedParameterNameException;
283
import es.unex.sextante.outputs.OutputVectorLayer;
284

    
285
public class VectorizeAlgorithm
286
         extends
287
            GeoAlgorithm {
288

    
289
   public static final String LAYER  = "LAYER";
290
   public static final String RESULT = "RESULT";
291

    
292
   private IRasterLayer       m_Window;
293
   private IVectorLayer       m_Polygons;
294
   private int                m_iNX, m_iNY;
295
   private int[][]            m_Lock;
296
   private char[][]           m_Area;
297

    
298

    
299
   @Override
300
   public void defineCharacteristics() {
301

    
302
      setName(Sextante.getText("Vectorize_raster_layer__polygons"));
303
      setGroup(Sextante.getText("Vectorization"));
304
      setUserCanDefineAnalysisExtent(false);
305

    
306
      try {
307
         m_Parameters.addInputRasterLayer(LAYER, Sextante.getText("Input_layer"), true);
308
         addOutputVectorLayer(RESULT, Sextante.getText("Result"), OutputVectorLayer.SHAPE_TYPE_POLYGON);
309
      }
310
      catch (final RepeatedParameterNameException e) {
311
         Sextante.addErrorToLog(e);
312
      }
313

    
314
   }
315

    
316

    
317
   @Override
318
   public boolean processAlgorithm() throws GeoAlgorithmExecutionException {
319

    
320
      final String sFields[] = new String[2];
321
      final Class types[] = { Integer.class, Double.class };
322

    
323
      m_Window = m_Parameters.getParameterValueAsRasterLayer(LAYER);
324

    
325
      m_Window.setFullExtent();
326

    
327
      sFields[0] = "ID";
328
      sFields[1] = m_Window.getName();
329

    
330
      m_Polygons = getNewVectorLayer(RESULT, Sextante.getText("Resultado"), IVectorLayer.SHAPE_TYPE_POLYGON, types, sFields);
331

    
332
      createPolygons();
333

    
334
      return !m_Task.isCanceled();
335

    
336
   }
337

    
338

    
339
   private void createPolygons() {
340

    
341
      int x, y, ID;
342
      double dValue;
343

    
344
      m_iNX = m_Window.getNX();
345
      m_iNY = m_Window.getNY();
346

    
347
      m_Lock = new int[m_iNY][m_iNX];
348
      m_Area = new char[m_iNY + 1][m_iNX + 1];
349

    
350
      for (y = 0, ID = 1; (y < m_iNY) && setProgress(y, m_iNY); y++) {
351
         for (x = 0; x < m_iNX; x++) {
352
            dValue = m_Window.getCellValueAsDouble(x, y);
353
            if (!m_Window.isNoDataValue(dValue) && (m_Lock[y][x] == 0)) {
354
               Discrete_Lock(x, y, ID);
355
               Discrete_Area(x, y, ID);
356
               ID++;
357
            }
358
         }
359
      }
360

    
361
   }
362

    
363

    
364
   private void Discrete_Lock(int x,
365
                              int y,
366
                              final int ID) {
367

    
368
      final int xTo[] = { 0, 1, 0, -1 }, yTo[] = { 1, 0, -1, 0 };
369

    
370
      final char goDir[] = { 1, 2, 4, 8 };
371

    
372
      boolean isBorder, doRecurse;
373

    
374
      char goTemp = 0;
375

    
376
      char[] goStack = new char[50];
377
      int[] xStack = new int[50];
378
      int[] yStack = new int[50];
379

    
380
      int i, ix, iy, iStack = 0;
381

    
382
      double dValue, dValue2;
383

    
384
      dValue = m_Window.getCellValueAsDouble(x, y);
385

    
386
      for (iy = 0; iy <= m_iNY; iy++) {
387
         for (ix = 0; ix <= m_iNX; ix++) {
388
            m_Area[iy][ix] = 0;
389
         }
390
      }
391

    
392
      do {
393
         if (m_Lock[y][x] == 0) {
394

    
395
            if (goStack.length <= iStack) {
396
               final char[] cAux = new char[goStack.length + 50];
397
               System.arraycopy(goStack, 0, cAux, 0, goStack.length);
398
               goStack = cAux;
399
               int[] iAux = new int[xStack.length + 50];
400
               System.arraycopy(xStack, 0, iAux, 0, xStack.length);
401
               xStack = iAux;
402
               iAux = new int[yStack.length + 50];
403
               System.arraycopy(yStack, 0, iAux, 0, yStack.length);
404
               yStack = iAux;
405
            }
406

    
407
            goStack[iStack] = 0;
408
            m_Lock[y][x] = ID;
409

    
410
            for (i = 0; i < 4; i++) {
411
               ix = x + xTo[i];
412
               iy = y + yTo[i];
413

    
414
               isBorder = true;
415

    
416
               dValue2 = m_Window.getCellValueAsDouble(ix, iy);
417
               if ((ix >= 0) && (ix < m_iNX) && (iy >= 0) && (iy < m_iNY) && (dValue == dValue2)) {
418
                  isBorder = false;
419
                  if (m_Lock[iy][ix] == 0) {
420
                     goStack[iStack] |= goDir[i];
421
                  }
422
               }
423

    
424
               if (isBorder) {
425
                  switch (i) {
426
                     case 0:
427
                        m_Area[y + 1][x]++;
428
                        m_Area[y + 1][x + 1]++;
429
                        break;
430

    
431
                     case 1:
432
                        m_Area[y][x + 1]++;
433
                        m_Area[y + 1][x + 1]++;
434
                        break;
435

    
436
                     case 2:
437
                        m_Area[y][x]++;
438
                        m_Area[y][x + 1]++;
439
                        break;
440

    
441
                     case 3:
442
                        m_Area[y][x]++;
443
                        m_Area[y + 1][x]++;
444
                        break;
445
                  }
446
               }
447
            }
448
         }
449

    
450
         doRecurse = false;
451

    
452
         for (i = 0; i < 4; i++) {
453
            if ((goStack[iStack] & goDir[i]) != 0) {
454
               if (doRecurse) {
455
                  goTemp |= goDir[i];
456
               }
457
               else {
458
                  goTemp = 0;
459
                  doRecurse = true;
460
                  xStack[iStack] = x;
461
                  yStack[iStack] = y;
462
                  x = x + xTo[i];
463
                  y = y + yTo[i];
464
               }
465
            }
466
         }
467

    
468
         if (doRecurse) {
469
            goStack[iStack++] = goTemp;
470
         }
471
         else if (iStack > 0) {
472
            iStack--;
473
            x = xStack[iStack];
474
            y = yStack[iStack];
475
         }
476
      }
477
      while (iStack > 0);
478

    
479
   }
480

    
481

    
482
   private void Discrete_Area(int x,
483
                              int y,
484
                              final int ID) {
485

    
486
      final int xTo[] = { 0, 1, 0, -1 }, yTo[] = { 1, 0, -1, 0 };
487

    
488
      final int xLock[] = { 0, 0, -1, -1 }, yLock[] = { 0, -1, -1, 0 };
489

    
490
      boolean bContinue, bStart;
491

    
492
      int i, ix, iy, ix1, iy1, dir, iStart;
493

    
494
      final double xMin = m_Window.getWindowGridExtent().getXMin(), yMax = m_Window.getWindowGridExtent().getYMax();
495
      final double dCellSize = m_Window.getWindowCellSize();
496
      double xFirst = 0, yFirst = 0;
497

    
498
      final ArrayList coordinates = new ArrayList();
499
      final Object values[] = new Object[2];
500
      values[0] = new Integer(ID);
501
      values[1] = new Double(m_Window.getCellValueAsDouble(x, y));
502

    
503
      xFirst = xMin + (x) * dCellSize;
504
      yFirst = yMax - (y) * dCellSize;
505
      coordinates.add(new Coordinate(xFirst, yFirst));
506

    
507
      iStart = 0;
508
      bStart = true;
509

    
510
      do {
511
         coordinates.add(new Coordinate(xMin + (x) * dCellSize, yMax - (y) * dCellSize));
512

    
513
         m_Area[y][x] = 0;
514
         bContinue = false;
515

    
516
         while (true) {
517
            // assure clockwise direction at starting point
518
            if (bStart) {
519
               for (i = 0; i < 4; i++) {
520
                  ix = x + xTo[i];
521
                  iy = y + yTo[i];
522

    
523
                  if ((ix >= 0) && (ix <= m_iNX) && (iy >= 0) && (iy <= m_iNY) && (m_Area[iy][ix] > 0)) {
524
                     // check, if inside situated cell (according to current direction) is locked
525
                     ix1 = x + xLock[i];
526
                     iy1 = y + yLock[i];
527

    
528
                     if ((ix1 >= 0) && (ix1 <= m_iNX) && (iy1 >= 0) && (iy1 <= m_iNY) && (m_Lock[iy1][ix1] == ID)) {
529
                        x = ix;
530
                        y = iy;
531
                        iStart = (i + 3) % 4;
532
                        bContinue = true;
533
                        bStart = false;
534
                        break;
535
                     }
536
                  }
537
               }
538
            }
539
            else {
540
               for (i = iStart; i < iStart + 4; i++) {
541
                  dir = i % 4;
542
                  ix = x + xTo[dir];
543
                  iy = y + yTo[dir];
544

    
545
                  if ((ix >= 0) && (ix <= m_iNX) && (iy >= 0) && (iy <= m_iNY) && (m_Area[iy][ix] > 0)) {
546
                     if (i < iStart + 3) {
547
                        // check, if inside situated cell (according to current direction) is locked
548
                        ix1 = x + xLock[dir];
549
                        iy1 = y + yLock[dir];
550

    
551
                        if ((ix1 >= 0) && (ix1 <= m_iNX) && (iy1 >= 0) && (iy1 <= m_iNY) && (m_Lock[iy1][ix1] == ID)) {
552
                           x = ix;
553
                           y = iy;
554
                           iStart = (i + 3) % 4;
555
                           bContinue = true;
556
                           break;
557
                        }
558
                     }
559
                     else {
560
                        x = ix;
561
                        y = iy;
562
                        bContinue = true;
563
                        iStart = (i + 3) % 4;
564
                        break;
565
                     }
566
                  }
567
               }
568
            }
569

    
570
            break;
571
         };
572
      }
573
      while (bContinue);
574

    
575
      coordinates.add(new Coordinate(xFirst, yFirst));
576

    
577
      final Coordinate[] coords = new Coordinate[coordinates.size()];
578
      for (i = 0; i < coords.length; i++) {
579
         coords[i] = (Coordinate) coordinates.get(i);
580
      }
581

    
582
      final GeometryFactory gf = new GeometryFactory();
583

    
584
      if (coords.length > 1) {
585
         final LinearRing ring = gf.createLinearRing(coords);
586
         final Polygon polyg = gf.createPolygon(ring, null);
587
         m_Polygons.addFeature(polyg, values);
588
      }
589

    
590
   }
591

    
592
}