Statistics
| Revision:

root / trunk / extensions / extRasterTools-SE / src / org / gvsig / rastertools / vectorizacion / process / ContourLinesProcess.java @ 27442

History | View | Annotate | Download (13.8 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
*
3
* Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
*
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
*/
19
package org.gvsig.rastertools.vectorizacion.process;
20

    
21
import java.io.File;
22
import java.sql.Types;
23

    
24
import org.gvsig.fmap.raster.layers.FLyrRasterSE;
25
import org.gvsig.raster.RasterProcess;
26
import org.gvsig.raster.buffer.RasterBufferInvalidException;
27
import org.gvsig.raster.datastruct.Extent;
28
import org.gvsig.raster.grid.Grid;
29
import org.gvsig.raster.grid.GridException;
30
import org.gvsig.raster.grid.GridExtent;
31
import org.gvsig.raster.process.RasterTask;
32
import org.gvsig.raster.process.RasterTaskQueue;
33
import org.gvsig.raster.util.RasterToolsUtil;
34

    
35
import com.hardcode.gdbms.driver.exceptions.InitializeWriterException;
36
import com.hardcode.gdbms.engine.values.Value;
37
import com.hardcode.gdbms.engine.values.ValueFactory;
38
import com.iver.cit.gvsig.exceptions.visitors.StartWriterVisitorException;
39
import com.iver.cit.gvsig.exceptions.visitors.StopWriterVisitorException;
40
import com.iver.cit.gvsig.exceptions.visitors.VisitorException;
41
import com.iver.cit.gvsig.fmap.core.DefaultFeature;
42
import com.iver.cit.gvsig.fmap.core.FPolyline2D;
43
import com.iver.cit.gvsig.fmap.core.FShape;
44
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
45
import com.iver.cit.gvsig.fmap.core.IGeometry;
46
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
47
import com.iver.cit.gvsig.fmap.drivers.DXFLayerDefinition;
48
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
49
import com.iver.cit.gvsig.fmap.drivers.LayerDefinition;
50
import com.iver.cit.gvsig.fmap.drivers.SHPLayerDefinition;
51
import com.iver.cit.gvsig.fmap.edition.DefaultRowEdited;
52
import com.iver.cit.gvsig.fmap.edition.IRowEdited;
53
import com.iver.cit.gvsig.fmap.edition.IWriter;
54
import com.iver.cit.gvsig.fmap.edition.writers.dxf.DxfFieldsMapping;
55
import com.iver.cit.gvsig.fmap.edition.writers.dxf.DxfWriter;
56
import com.iver.cit.gvsig.fmap.edition.writers.shp.ShpWriter;
57
/**
58
 * Este proceso vectoriza la capa de entrada que debe estar ya preprocesada.
59
 * 03/07/2008
60
 * @author Victor Olaya (volaya@ya.com)
61
 * @author Nacho Brodin nachobrodin@gmail.com
62
 */
63
public class ContourLinesProcess extends RasterProcess {
64
        private FLyrRasterSE                  lyr                 = null;
65
        private double                        min                 = 0;
66
        private double                        max                 = 0;
67
        private double                        distance            = 0;
68
        private Extent                        extent              = null;
69
        private String                        fileName            = null;
70
        
71
        private char[][]                      m_Row               = null;
72
        private char[][]                      m_Col               = null; 
73
        private Grid                          grid                = null;
74
        private IWriter                       writer              = null;
75
        private int                           m_iGeometry         = 0;
76
        private double                        percent             = 0;
77
        
78
        private class NextContourInfo {
79
                public int iDir;
80
                public int x;
81
                public int y;
82
                public boolean doRow;
83
        }
84
        
85
        /**
86
         * Par?metros obligatorios al proceso:
87
         * <UL>
88
         * <LI></LI>
89
         * <LI>filename: Nombre del fichero de salida</LI>
90
         * <LI></LI>
91
         * <LI></LI>
92
         * <LI></LI>
93
         * <LI></LI>
94
         * </UL> 
95
         */
96
        public void init() {
97
                lyr = getLayerParam("layer");
98
                fileName = getStringParam("filename");
99
                min = getDoubleParam("min");
100
                max = getDoubleParam("max");
101
                distance = getDoubleParam("distance");
102
                extent = getExtentParam("extent");
103
                
104
                String sFields[] = new String[2];
105
                sFields[0] = "ID";
106
                sFields[1] = lyr.getName();
107
                
108
                LayerDefinition tableDef = null;
109
                if(fileName.endsWith(".dxf")) {
110
                        writer = new DxfWriter();
111
                        ((DxfWriter)writer).setFile(new File(fileName));
112
                        ((DxfWriter)writer).setProjection(lyr.getProjection());
113
                        tableDef = new DXFLayerDefinition();
114

    
115
                        DxfFieldsMapping fieldsMapping = new DxfFieldsMapping();
116
                        ((DxfWriter)writer).setFieldMapping(fieldsMapping);
117
                }
118
                if(fileName.endsWith(".shp")) {
119
                        writer = new ShpWriter();
120
                        ((ShpWriter)writer).setFile(new File(fileName));
121
                        tableDef = new SHPLayerDefinition();
122
                }
123
                tableDef.setShapeType(FShape.LINE);
124
                
125
                int types[] = {Types.DOUBLE, Types.DOUBLE};
126
                FieldDescription[] fields = new FieldDescription[sFields.length];
127
                for (int i = 0; i < fields.length; i++) {
128
                        fields[i] = new FieldDescription();
129
                        fields[i].setFieldName(sFields[i]);
130
                        fields[i].setFieldType(types[i]);
131
                        fields[i].setFieldLength(getDataTypeLength(types[i]));
132
                        fields[i].setFieldDecimalCount(5);
133
                }
134
                tableDef.setFieldsDesc(fields);
135
                tableDef.setName(fileName);
136

    
137
                try {
138
                        writer.initialize(tableDef);
139
                        writer.preProcess();        
140
                } catch (InitializeWriterException e) {
141
                        RasterToolsUtil.messageBoxError("error_init_vectlayer", null, e);
142
                } catch (StartWriterVisitorException e) {
143
                        RasterToolsUtil.messageBoxError("error_init_vectlayer", null, e);
144
                }
145
        }
146

    
147
        /**
148
         * Tarea de recorte
149
         */
150
        public void process() throws InterruptedException {
151
                GridExtent ge = null;
152
                insertLineLog("Contour Lines");
153
                if(extent != null)
154
                        ge = new GridExtent(extent, lyr.getCellSize());
155
                
156
                try {
157
                        grid = new Grid(lyr.getDataSource(), new int[]{0}, ge);
158
                        if( min <= max && distance > 0 ) {
159
                                if( min < grid.getMinValue() )
160
                                        min += distance * (int)((grid.getMinValue() - min) / distance);
161
                                
162
                                if( max > grid.getMaxValue() )
163
                                        max = grid.getMaxValue();
164

    
165
                                createContours(min, max, distance);
166
                                writer.postProcess();
167
                        }
168
                } catch (RasterBufferInvalidException e) {
169
                        RasterToolsUtil.messageBoxError("error_loading_grid", this, e);
170
                } catch (GridException e) {
171
                        RasterToolsUtil.messageBoxError("error_loading_grid", this, e);
172
                } catch (StopWriterVisitorException e) {
173
                        RasterToolsUtil.messageBoxError("error_closing_grid", this, e);
174
                } catch (VisitorException e) {
175
                        RasterToolsUtil.messageBoxError("", this, e);
176
                } finally {
177
                        if (incrementableTask != null) {
178
                                incrementableTask.processFinalize();
179
                                incrementableTask = null;
180
                        }
181
                }
182
                if(externalActions != null)
183
                        externalActions.end(fileName);
184
        }
185
        
186
        private void createContours(double dMin, double dMax, double dDistance) throws InterruptedException, GridException, VisitorException {
187
                int x, y;
188
                int i;
189
                int ID;
190
                int iNX,iNY;
191
                double dZ;
192
                double dValue = 0;
193
                RasterTask task = RasterTaskQueue.get(Thread.currentThread().toString());
194

    
195
                iNX = grid.getNX();
196
                iNY = grid.getNY();
197

    
198
                m_Row = new char[iNY][iNX];
199
                m_Col = new char[iNY][iNX];
200

    
201
                if( dDistance <= 0 )
202
                        dDistance= 1;
203
                
204
                percent = 0;
205
                for(dZ = dMin, ID = 0; dZ <= dMax; dZ += dDistance) {
206
                        double increment = (25 / (double)(iNY * (((dMax - dMin) / dDistance) + 1)));
207
                        for(y = 0; y < iNY - 1; y++) {
208
                                percent += increment;
209
                                for(x = 0; x < iNX - 1; x++) {
210
                                        dValue = grid.getCellValue(y, x);
211
                                        if( dValue >= dZ ) {
212
                                                m_Row[y][x]        = (char) (grid.getCellValue(y, x + 1) <  dZ ? 1 : 0);
213
                                                m_Col[y][x]        = (char) (grid.getCellValue(y + 1, x) <  dZ ? 1 : 0);
214
                                        }
215
                                        else {
216
                                                m_Row[y][x]        = (char) (grid.getCellValue(y, x + 1) >= dZ ? 1 : 0);
217
                                                m_Col[y][x]        = (char) (grid.getCellValue(y + 1, x) >= dZ ? 1 : 0);
218
                                        }
219
                                }
220
                                if(task.getEvent() != null)
221
                                        task.manageEvent(task.getEvent());
222
                        }
223

    
224
                        increment = (75 / (double)(iNY * (((dMax - dMin) / dDistance) + 1)));
225
                        for(y = 0; y < iNY - 1; y++) {
226
                                percent += increment;
227
                                for(x = 0; x < iNX - 1; x++) {
228
                                        if(m_Row[y][x] != 0) {
229
                                                for(i = 0; i < 2; i++) 
230
                                                        findContour(x, y, dZ, true, ID++);
231
                                                m_Row[y][x]        = 0;
232
                                        }
233

    
234
                                        if(m_Col[y][x] != 0) {
235
                                                for(i=0; i<2; i++)
236
                                                        findContour(x, y, dZ, false, ID++);
237
                                                m_Col[y][x]        = 0;
238
                                        }
239
                                }
240
                                if(task.getEvent() != null)
241
                                        task.manageEvent(task.getEvent());
242
                        }
243
                }
244
        }
245

    
246
        private void findContour(int x, int y, double z, boolean doRow, int ID) throws GridException, InterruptedException, VisitorException {
247
                boolean doContinue = true;
248
                boolean bIsFirstPoint = true;
249
                int        zx        = doRow ? x + 1 : x;
250
                int zy        = doRow ? y : y + 1;
251
                double d = 0;
252
                double        xPos, yPos;
253
                double         xMin = grid.getGridExtent().getMin().getX();
254
                double         yMax = grid.getGridExtent().getMax().getY();
255
                FPolyline2D line;
256
                Value values[] = new Value[2];
257
                NextContourInfo info = new NextContourInfo();
258
                GeneralPathX genPathX = new GeneralPathX();
259

    
260
                info.x = x;
261
                info.y = y;
262
                info.iDir = 0;
263
                info.doRow = doRow;
264

    
265
                do{
266
                        d = grid.getCellValue(info.y, info.x);
267
                        d = (d - z) / (d - grid.getCellValue(zy, zx));
268

    
269
                        xPos = xMin + grid.getCellSize() * (info.x + d * (zx - info.x) + 0.5);
270
                        yPos = yMax - grid.getCellSize() * (info.y + d * (zy - info.y) + 0.5);
271

    
272
                        if (bIsFirstPoint) {
273
                                genPathX.moveTo(xPos, yPos);
274
                                bIsFirstPoint = false;
275
                        } else
276
                                genPathX.lineTo(xPos, yPos);
277

    
278
                        if( !findNextContour(info) )
279
                                doContinue        = findNextContour(info);
280

    
281
                        info.iDir = (info.iDir + 5) % 8;
282

    
283
                        if(info.doRow) {
284
                                m_Row[info.y][info.x]        = 0;
285
                                zx = info.x + 1;
286
                                zy = info.y;
287
                        } else {
288
                                m_Col[info.y][info.x]        = 0;
289
                                zx = info.x;
290
                                zy = info.y + 1;
291
                        }
292

    
293
                }
294
                while(doContinue);
295

    
296
                values[0] = ValueFactory.createValue(ID);
297
                values[1] = ValueFactory.createValue(z);
298

    
299
                line =  new FPolyline2D(genPathX);
300

    
301

    
302
                addShape(line, values);
303
        }
304

    
305
        private boolean findNextContour(NextContourInfo info) {
306
                boolean        doContinue;
307

    
308
                if(info.doRow) {
309
                        switch(info.iDir) {
310
                        case 0:
311
                                if(m_Row[info.y + 1][info.x] != 0) {
312
                                        info.y++;
313
                                        info.iDir = 0;
314
                                        doContinue = true;
315
                                        break;
316
                                }
317
                        case 1:
318
                                if(m_Col[info.y][info.x + 1] != 0) {
319
                                        info.x++;
320
                                        info.iDir = 1;
321
                                        info.doRow = false;
322
                                        doContinue = true;
323
                                        break;
324
                                }
325
                        case 2:
326
                        case 3:
327
                                if(info.y-1 >= 0) {
328
                                        if(m_Col[info.y - 1][info.x + 1] != 0) {
329
                                                info.x++;
330
                                                info.y--;
331
                                                info.doRow = false;
332
                                                info.iDir = 3;
333
                                                doContinue = true;
334
                                                break;
335
                                        }
336
                                }
337
                        case 4:
338
                                if(info.y-1>=0) {
339
                                        if(m_Row[info.y - 1][info.x]!= 0) {
340
                                                info.y--;
341
                                                info.iDir = 4;
342
                                                doContinue = true;
343
                                                break;
344
                                        }
345
                                }
346
                        case 5:
347
                                if(info.y-1>=0) {
348
                                        if(m_Col[info.y - 1][info.x] != 0) {
349
                                                info.y--;
350
                                                info.doRow = false;
351
                                                info.iDir = 5 ;
352
                                                doContinue = true;
353
                                                break;
354
                                        }
355
                                }
356
                        case 6:
357
                        case 7:
358
                                if(m_Col[info.y][info.x]!= 0) {
359
                                        info.doRow = false;
360
                                        info.iDir = 7;
361
                                        doContinue = true;
362
                                        break;
363
                                }
364
                        default:
365
                                info.iDir = 0;
366
                                doContinue = false;
367
                        }
368
                }
369
                else{
370
                        switch(info.iDir) {
371
                        case 0:
372
                        case 1:
373
                                if(m_Row[info.y + 1][info.x] != 0) {
374
                                        info.y++;
375
                                        info.doRow = true;
376
                                        info.iDir = 1;
377
                                        doContinue = true;
378
                                        break;
379
                                }
380
                        case 2:
381
                                if(m_Col[info.y][info.x + 1] != 0) {
382
                                        info.x++;
383
                                        info.iDir = 2;
384
                                        doContinue = true;
385
                                        break;
386
                                }
387
                        case 3:
388
                                if(m_Row[info.y][info.x] != 0) {
389
                                        info.doRow = true;
390
                                        info.iDir = 3;
391
                                        doContinue = true;
392
                                        break;
393
                                }
394
                        case 4:
395
                        case 5:
396
                                if(info.x-1>=0) {
397
                                        if(m_Row[info.y][info.x - 1] != 0) {
398
                                                info.x--;
399
                                                info.doRow = true;
400
                                                info.iDir = 5;
401
                                                doContinue = true;
402
                                                break;
403
                                        }
404
                                }
405
                        case 6:
406
                                if(info.x-1>=0) {
407
                                        if(m_Col[info.y][info.x - 1] != 0) {
408
                                                info.x--;
409
                                                info.iDir = 6;
410
                                                doContinue = true;
411
                                                break;
412
                                        }
413
                                }
414
                        case 7:
415
                                if(info.x-1 >= 0) {
416
                                        if(m_Row[info.y + 1][info.x - 1] != 0) {
417
                                                info.x--;
418
                                                info.y++;
419
                                                info.doRow = true;
420
                                                info.iDir = 7;
421
                                                doContinue = true;
422
                                                break;
423
                                        }
424
                                }
425
                        default:
426
                                info.iDir = 0;
427
                                doContinue = false;
428
                        }
429
                }
430

    
431
                return(doContinue);
432
        }
433
        
434
        /*
435
         * (non-Javadoc)
436
         * @see org.gvsig.gui.beans.incrementabletask.IIncrementable#getPercent()
437
         */
438
        public int getPercent() {
439
                return (int)percent;
440
        }
441

    
442
        /*
443
         * (non-Javadoc)
444
         * @see org.gvsig.gui.beans.incrementabletask.IIncrementable#getTitle()
445
         */
446
        public String getTitle() {
447
                return RasterToolsUtil.getText(this, "vectorization");
448
        }
449
        
450
        public void addShape(FShape shape, Value[] value) throws VisitorException  {
451
                if (shape == null) 
452
                        return;
453
                IGeometry geom = ShapeFactory.createGeometry(shape);
454
                addGeometry(geom, value);
455
        }
456

    
457
        public void addGeometry(IGeometry geom, Value[] value) throws VisitorException {
458
                DefaultFeature feat = new DefaultFeature(geom, value, Integer.toString(m_iGeometry));
459
                IRowEdited editFeat = new DefaultRowEdited(feat, IRowEdited.STATUS_MODIFIED, m_iGeometry);
460
                m_iGeometry++;
461
                writer.process(editFeat);
462
        }
463
        
464
        /**
465
                 * Returns the length of field
466
                 * @param dataType
467
                 * @return length of field
468
                 */
469
        public int getDataTypeLength(int dataType) {
470
                switch (dataType) {
471
                case Types.NUMERIC:
472
                case Types.DOUBLE:
473
                case Types.REAL:
474
                case Types.FLOAT:
475
                case Types.BIGINT:
476
                case Types.INTEGER:
477
                case Types.DECIMAL:
478
                        return 20;
479
                case Types.CHAR:
480
                case Types.VARCHAR:
481
                case Types.LONGVARCHAR:
482
                        return 254;
483
                case Types.DATE:
484
                        return 8;
485
                case Types.BOOLEAN:
486
                case Types.BIT:
487
                        return 1;
488
                }
489
                return 0;
490
        }
491
}