Statistics
| Revision:

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

History | View | Annotate | Download (13.1 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.util.RasterToolsUtil;
32

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

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

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

    
144
        /**
145
         * Tarea de recorte
146
         */
147
        public void process() throws InterruptedException {
148
                GridExtent ge = null;
149
                if(extent != null)
150
                        ge = new GridExtent(extent, lyr.getCellSize());
151
                try {
152
                        grid = new Grid(lyr.getDataSource(), new int[]{0}, ge);
153

    
154
                        if( min <= max && distance > 0 ) {
155
                                if( min < grid.getMinValue() )
156
                                        min += distance * (int)((grid.getMinValue() - min) / distance);
157
                                
158
                                if( max > grid.getMaxValue() )
159
                                        max = grid.getMaxValue();
160

    
161
                                createContours(min, max, distance);
162
                                writer.postProcess();
163
                        }
164
                } catch (RasterBufferInvalidException e) {
165
                        RasterToolsUtil.messageBoxError("error_loading_grid", this, e);
166
                } catch (GridException e) {
167
                        RasterToolsUtil.messageBoxError("error_loading_grid", this, e);
168
                } catch (StopWriterVisitorException e) {
169
                        RasterToolsUtil.messageBoxError("error_closing_grid", this, e);
170
                } catch (Exception e) {
171
                        RasterToolsUtil.messageBoxError("error_closing_grid", this, e);
172
                } finally {
173
                        if(externalActions != null)
174
                                externalActions.end(fileName);
175
                }
176
        }
177
        
178
        private void createContours(double dMin, double dMax, double dDistance) throws Exception {
179
                int x, y;
180
                int i;
181
                int ID;
182
                int iNX,iNY;
183
                double dZ;
184
                double dValue = 0;
185

    
186
                iNX = grid.getNX();
187
                iNY = grid.getNY();
188

    
189
                m_Row = new char[iNY][iNX];
190
                m_Col = new char[iNY][iNX];
191

    
192
                if( dDistance <= 0 )
193
                        dDistance= 1;
194

    
195
                double increment = (25 / (double)iNY);
196
                for(dZ = dMin, ID = 0; dZ <= dMax; dZ += dDistance) {
197
                        for(y = 0; y < iNY - 1; y++) {
198
                                percent += increment;
199
                                for(x = 0; x < iNX - 1; x++) {
200
                                        dValue = grid.getCellValue(y, x);
201
                                        if( dValue >= dZ ) {
202
                                                m_Row[y][x]        = (char) (grid.getCellValue(y, x + 1) <  dZ ? 1 : 0);
203
                                                m_Col[y][x]        = (char) (grid.getCellValue(y + 1, x) <  dZ ? 1 : 0);
204
                                        }
205
                                        else {
206
                                                m_Row[y][x]        = (char) (grid.getCellValue(y, x + 1) >= dZ ? 1 : 0);
207
                                                m_Col[y][x]        = (char) (grid.getCellValue(y + 1, x) >= dZ ? 1 : 0);
208
                                        }
209
                                }
210
                        }
211

    
212
                        increment = (75 / (double)iNY);
213
                        for(y = 0; y < iNY - 1; y++) {
214
                                percent += increment;
215
                                for(x = 0; x < iNX - 1; x++) {
216
                                        if(m_Row[y][x] != 0) {
217
                                                for(i = 0; i < 2; i++) 
218
                                                        findContour(x, y, dZ, true, ID++);
219
                                                m_Row[y][x]        = 0;
220
                                        }
221

    
222
                                        if(m_Col[y][x] != 0) {
223
                                                for(i=0; i<2; i++)
224
                                                        findContour(x, y, dZ, false, ID++);
225
                                                m_Col[y][x]        = 0;
226
                                        }
227
                                }
228
                        }
229
                }
230
        }
231

    
232
        private void findContour(int x, int y, double z, boolean doRow, int ID) throws Exception {
233
                boolean doContinue = true;
234
                boolean bIsFirstPoint = true;
235
                int        zx        = doRow ? x + 1 : x;
236
                int zy        = doRow ? y : y + 1;
237
                double d = 0;
238
                double        xPos, yPos;
239
                double         xMin = grid.getGridExtent().getMin().getX();
240
                double         yMax = grid.getGridExtent().getMax().getY();
241
                FPolyline2D line;
242
                Value values[] = new Value[2];
243
                NextContourInfo info = new NextContourInfo();
244
                GeneralPathX genPathX = new GeneralPathX();
245

    
246
                info.x = x;
247
                info.y = y;
248
                info.iDir = 0;
249
                info.doRow = doRow;
250

    
251
                do{
252
                        d = grid.getCellValue(info.y, info.x);
253
                        d = (d - z) / (d - grid.getCellValue(zy, zx));
254

    
255
                        xPos = xMin + grid.getCellSize() * (info.x + d * (zx - info.x) + 0.5);
256
                        yPos = yMax - grid.getCellSize() * (info.y + d * (zy - info.y) + 0.5);
257

    
258
                        if (bIsFirstPoint) {
259
                                genPathX.moveTo(xPos, yPos);
260
                                bIsFirstPoint = false;
261
                        } else
262
                                genPathX.lineTo(xPos, yPos);
263

    
264
                        if( !findNextContour(info) )
265
                                doContinue        = findNextContour(info);
266

    
267
                        info.iDir = (info.iDir + 5) % 8;
268

    
269
                        if(info.doRow) {
270
                                m_Row[info.y][info.x]        = 0;
271
                                zx = info.x + 1;
272
                                zy = info.y;
273
                        } else {
274
                                m_Col[info.y][info.x]        = 0;
275
                                zx = info.x;
276
                                zy = info.y + 1;
277
                        }
278

    
279
                }
280
                while(doContinue);
281

    
282
                values[0] = ValueFactory.createValue(ID);
283
                values[1] = ValueFactory.createValue(z);
284

    
285
                line =  new FPolyline2D(genPathX);
286

    
287

    
288
                addShape(line, values);
289
        }
290

    
291
        private boolean findNextContour(NextContourInfo info) {
292
                boolean        doContinue;
293

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

    
417
                return(doContinue);
418
        }
419
        
420
        /*
421
         * (non-Javadoc)
422
         * @see org.gvsig.gui.beans.incrementabletask.IIncrementable#getPercent()
423
         */
424
        public int getPercent() {
425
                return (int)percent;
426
        }
427

    
428
        /*
429
         * (non-Javadoc)
430
         * @see org.gvsig.gui.beans.incrementabletask.IIncrementable#getTitle()
431
         */
432
        public String getTitle() {
433
                return RasterToolsUtil.getText(this, "vectorization");
434
        }
435
        
436
        public void addShape(FShape shape, Value[] value)  throws Exception {
437
                if (shape == null) 
438
                        return;
439
                IGeometry geom = ShapeFactory.createGeometry(shape);
440
                addGeometry(geom, value);
441
        }
442

    
443
        public void addGeometry(IGeometry geom, Value[] value) throws Exception {
444
                DefaultFeature feat = new DefaultFeature(geom, value, Integer.toString(m_iGeometry));
445
                IRowEdited editFeat = new DefaultRowEdited(feat, IRowEdited.STATUS_MODIFIED, m_iGeometry);
446
                m_iGeometry++;
447
                writer.process(editFeat);
448
        }
449
        
450
        /**
451
                 * Returns the length of field
452
                 * @param dataType
453
                 * @return length of field
454
                 */
455
        public int getDataTypeLength(int dataType) {
456
                switch (dataType) {
457
                case Types.NUMERIC:
458
                case Types.DOUBLE:
459
                case Types.REAL:
460
                case Types.FLOAT:
461
                case Types.BIGINT:
462
                case Types.INTEGER:
463
                case Types.DECIMAL:
464
                        return 20;
465
                case Types.CHAR:
466
                case Types.VARCHAR:
467
                case Types.LONGVARCHAR:
468
                        return 254;
469
                case Types.DATE:
470
                        return 8;
471
                case Types.BOOLEAN:
472
                case Types.BIT:
473
                        return 1;
474
                }
475
                return 0;
476
        }
477
}