Statistics
| Revision:

gvsig-raster / org.gvsig.raster.tools / trunk / org.gvsig.raster.tools / org.gvsig.raster.tools.algorithm / org.gvsig.raster.tools.algorithm.reproject / src / main / java / org / gvsig / raster / tools / algorithm / reproject / Reproject.java @ 1747

History | View | Annotate | Download (12.3 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
5
* 
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
* 
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
* GNU General Public License for more details.
15
* 
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
* MA  02110-1301, USA.
20
* 
21
*/
22
package org.gvsig.raster.tools.algorithm.reproject;
23

    
24
import java.awt.geom.AffineTransform;
25
import java.awt.geom.Point2D;
26
import java.io.File;
27

    
28
import org.cresques.cts.ICoordTrans;
29
import org.cresques.cts.IProjection;
30
import org.gvsig.fmap.dal.coverage.RasterLocator;
31
import org.gvsig.fmap.dal.coverage.RasterManager;
32
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
33
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
34
import org.gvsig.fmap.dal.coverage.datastruct.NoData;
35
import org.gvsig.fmap.dal.coverage.datastruct.Params;
36
import org.gvsig.fmap.dal.coverage.exception.InvalidSetViewException;
37
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
38
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
39
import org.gvsig.fmap.dal.coverage.store.DataServerWriter;
40
import org.gvsig.fmap.dal.coverage.store.RasterDataStore;
41
import org.gvsig.fmap.dal.coverage.store.RasterQuery;
42
import org.gvsig.fmap.dal.coverage.store.RasterWriter;
43
import org.gvsig.raster.tools.algorithm.base.process.RasterProcess;
44
import org.gvsig.raster.tools.algorithm.base.util.Interpolation;
45

    
46

    
47
/**
48
 * Reprojects a RasterDataStore. 
49
 *
50
 * @version 30/04/2008
51
 * @author Nacho Brodin nachobrodin@gmail.com
52
 */
53
public class Reproject {
54
        private RasterDataStore   store                 = null;
55
        private String            pathDest              = null;
56
        private int               percent               = 0;
57
        private int               interpolationMethod   = 0;
58
        private Interpolation     interpolation         = null; 
59
        private RasterProcess     process               = null;
60

    
61
        /**
62
         * Constructor de la clase.
63
         * @param lyr
64
         * @param pathDest Ruta de destino
65
         */
66
        public Reproject(RasterDataStore store, String pathDest, int inter, RasterProcess process) {
67
                this.store = store;
68
                this.pathDest = pathDest;
69
                this.interpolationMethod = inter;
70
                this.process = process;
71
        }
72

    
73
        /**
74
         * M?todo para la transformaci?n del raster.
75
         * @param destinationSrs Proyecci?n destino
76
         */
77
        public int warp(IProjection destinationSrs, IProjection sourceSrs, int w, int h, double cellSize) throws ReprojectException {
78
                if (store == null)
79
                        throw new ReprojectException("Capa no valida.");
80
                if (!store.isReproyectable())
81
                        throw new ReprojectException("Esta capa no se puede reproyectar.");
82
                if (destinationSrs == null || destinationSrs.getAbrev() == null)
83
                        throw new ReprojectException("Proyecci?n de destino no valida.");
84

    
85

    
86
                File file = new File(pathDest);
87
                if (!file.getParentFile().canWrite())
88
                        throw new ReprojectException("Ruta de destino no valida.");
89

    
90
                ICoordTrans transf = sourceSrs.getCT(destinationSrs);
91
                Extent bbox = store.getExtent();
92
                Point2D ul = new Point2D.Double(bbox.getULX(), bbox.getULY());
93
                Point2D lr = new Point2D.Double(bbox.getLRX(), bbox.getLRY());
94
                //Point2D p = new Point2D.Double(lyr.getFullRasterExtent().getULX(), lyr.getFullRasterExtent().getULY());
95
                ul = transf.convert(ul, ul);
96
                lr = transf.convert(lr, lr);
97
                Extent newBbox = RasterLocator.getManager().getDataStructFactory().createExtent(ul, lr);
98
                
99
                if(w <= 0 || h <= 0 ) {
100
                        double[] size = getSize(bbox, newBbox);
101
                        w = (int)size[0];
102
                        h = (int)size[1];
103
                        cellSize = size[2];
104
                }
105
                int dataType = store.getDataType()[0];
106
                Buffer buf = RasterLocator.getManager().createBuffer(
107
                                store.getDataType()[0], w, h, store.getBandCount(), true);
108
                
109
                NoData nd = RasterLocator.getManager().getDataStructFactory().createDefaultNoData(
110
                                store.getBandCount(), dataType);
111
                
112
                RasterQuery query = RasterLocator.getManager().createQuery();
113
                query.setAllDrawableBands();
114
                query.setAreaOfInterest();
115
                query.setReadOnly(true);
116
                try {
117
                        ICoordTrans t = destinationSrs.getCT(sourceSrs);
118
                        Buffer sourceBuffer = store.query(query);
119
                        if(interpolationMethod < 0) {
120
                                for (int row = 0; row < buf.getHeight(); row++) {
121
                                        for (int col = 0; col < buf.getWidth(); col++) {
122
                                                Point2D p = transformPoint(newBbox, col, row, cellSize, t);
123
                                                writePixel(dataType, sourceBuffer, buf, p, col, row, nd);
124
                                        }
125
                                        process.updatePercent(row, buf.getHeight());
126
                                }
127
                        } else {
128
                                interpolation = new Interpolation(sourceBuffer);
129
                                for (int row = 0; row < buf.getHeight(); row++) {
130
                                        for (int col = 0; col < buf.getWidth(); col++) {
131
                                                Point2D p = transformPoint(newBbox, col, row, cellSize, t);
132
                                                writePixelInterpolated(dataType, sourceBuffer, buf, p, col, row, nd, interpolationMethod);
133
                                        }
134
                                        process.updatePercent(row, buf.getHeight());
135
                                }
136
                        }
137

    
138
                        export(pathDest, buf, cellSize, newBbox.getULX(), newBbox.getULY());
139
                } catch (RasterDriverException e) {
140
                        new ReprojectException("", e);
141
                } catch (ProcessInterruptedException e) {
142
                } catch (InvalidSetViewException e) {
143
                        new ReprojectException("", e);
144
                }
145
                
146
                return 0;
147
        }
148
        
149
        /**
150
         * Writes one pixel in the destination buffer
151
         * @param type
152
         * @param sourceBuffer
153
         * @param buf
154
         * @param p
155
         * @param col
156
         * @param row
157
         */
158
        private void writePixel(int type, Buffer sourceBuffer, Buffer buf, Point2D p, int col, int row, NoData nd) {
159
                if(type == Buffer.TYPE_BYTE) {
160
                        if(p.getX() > 0 && p.getX() < sourceBuffer.getWidth() && p.getY() > 0 && p.getY() < sourceBuffer.getHeight())
161
                                for (int iBand = 0; iBand < store.getBandCount(); iBand++) {
162
                                        //if(iBand == 0)
163
                                                //System.out.println("Row:" + row + " Col:" + col + "  Y:" + (int)p.getY() + " X:" + (int)p.getX());
164
                                        buf.setElem(row, col, iBand, sourceBuffer.getElemByte((int)p.getY(), (int)p.getX(), iBand));
165
                                }
166
                        else
167
                                for (int iBand = 0; iBand < store.getBandCount(); iBand++)
168
                                        buf.setElem(row, col, iBand, nd.getValue().byteValue());
169
                } else if(type == Buffer.TYPE_DOUBLE) {
170
                        if(p.getX() > 0 && p.getX() < sourceBuffer.getWidth() && p.getY() > 0 && p.getY() < sourceBuffer.getHeight())
171
                                for (int iBand = 0; iBand < store.getBandCount(); iBand++)
172
                                        buf.setElem(row, col, iBand, sourceBuffer.getElemDouble((int)p.getY(), (int)p.getX(), iBand));
173
                        else
174
                                for (int iBand = 0; iBand < store.getBandCount(); iBand++)
175
                                        buf.setElem(row, col, iBand, nd.getValue().doubleValue());
176
                } else if(type == Buffer.TYPE_FLOAT) {
177
                        if(p.getX() > 0 && p.getX() < sourceBuffer.getWidth() && p.getY() > 0 && p.getY() < sourceBuffer.getHeight())
178
                                for (int iBand = 0; iBand < store.getBandCount(); iBand++)
179
                                        buf.setElem(row, col, iBand, sourceBuffer.getElemFloat((int)p.getY(), (int)p.getX(), iBand));
180
                        else
181
                                for (int iBand = 0; iBand < store.getBandCount(); iBand++)
182
                                        buf.setElem(row, col, iBand, nd.getValue().floatValue());
183
                } else if(type == Buffer.TYPE_SHORT) {
184
                        if(p.getX() > 0 && p.getX() < sourceBuffer.getWidth() && p.getY() > 0 && p.getY() < sourceBuffer.getHeight())
185
                                for (int iBand = 0; iBand < store.getBandCount(); iBand++)
186
                                        buf.setElem(row, col, iBand, sourceBuffer.getElemShort((int)p.getY(), (int)p.getX(), iBand));
187
                        else
188
                                for (int iBand = 0; iBand < store.getBandCount(); iBand++)
189
                                        buf.setElem(row, col, iBand, nd.getValue().shortValue());
190
                } else if(type == Buffer.TYPE_INT) {
191
                        if(p.getX() > 0 && p.getX() < sourceBuffer.getWidth() && p.getY() > 0 && p.getY() < sourceBuffer.getHeight())
192
                                for (int iBand = 0; iBand < store.getBandCount(); iBand++)
193
                                        buf.setElem(row, col, iBand, sourceBuffer.getElemInt((int)p.getY(), (int)p.getX(), iBand));
194
                        else
195
                                for (int iBand = 0; iBand < store.getBandCount(); iBand++)
196
                                        buf.setElem(row, col, iBand, nd.getValue().intValue());
197
                } 
198
        }
199
        
200
        /**
201
         * Writes one pixel in the destination buffer
202
         * @param type
203
         * @param sourceBuffer
204
         * @param buf
205
         * @param p
206
         * @param col
207
         * @param row
208
         */
209
        private void writePixelInterpolated(int type, Buffer sourceBuffer, Buffer buf, Point2D p, int col, int row, NoData nd, int interpMethod) {
210
                double value = 0;
211
                if(p.getX() > 0 && p.getX() < sourceBuffer.getWidth() && p.getY() > 0 && p.getY() < sourceBuffer.getHeight())
212
                        for (int iBand = 0; iBand < store.getBandCount(); iBand++) {
213
                                if(interpMethod == 0) //Nearest neighbor
214
                                        value = interpolation.getNearestNeighbour(p.getX(), p.getY(), iBand);
215
                                if(interpMethod == 1) //Bilinear
216
                                        value = interpolation.getBilinearValue(p.getX(), p.getY(), iBand);
217
                                if(interpMethod == 2) //Inverse distance
218
                                        value = interpolation.getInverseDistance(p.getX(), p.getY(), iBand);
219
                                if(type == Buffer.TYPE_BYTE)
220
                                        buf.setElem(row, col, iBand, (byte)value);
221
                                else if(type == Buffer.TYPE_DOUBLE)
222
                                        buf.setElem(row, col, iBand, (double)value);
223
                                else if(type == Buffer.TYPE_FLOAT)
224
                                        buf.setElem(row, col, iBand, (float)value);
225
                                else if(type == Buffer.TYPE_SHORT)
226
                                        buf.setElem(row, col, iBand, (short)value);
227
                                else if(type == Buffer.TYPE_INT)
228
                                        buf.setElem(row, col, iBand, (int)value);
229
                        }
230
                else
231
                        for (int iBand = 0; iBand < store.getBandCount(); iBand++) {
232
                                if(type == Buffer.TYPE_BYTE)
233
                                        buf.setElem(row, col, iBand, nd.getValue().byteValue());
234
                                else if(type == Buffer.TYPE_DOUBLE)
235
                                        buf.setElem(row, col, iBand, nd.getValue().doubleValue());
236
                                else if(type == Buffer.TYPE_FLOAT)
237
                                        buf.setElem(row, col, iBand, nd.getValue().floatValue());
238
                                else if(type == Buffer.TYPE_SHORT)
239
                                        buf.setElem(row, col, iBand, nd.getValue().shortValue());
240
                                else if(type == Buffer.TYPE_INT)
241
                                        buf.setElem(row, col, iBand, nd.getValue().intValue());
242
                        }
243
        }
244
        
245
        /**
246
         * Transforms the upper left coordinate of a pixel using the transformation 
247
         * which is passed by parameter
248
         * @param p
249
         * @param newBbox
250
         * @param col
251
         * @param row
252
         * @param cellSize
253
         * @param t
254
         */
255
        private Point2D transformPoint(Extent newBbox, int col, int row, double cellSize, ICoordTrans t) {
256
                Point2D p = new Point2D.Double(
257
                                newBbox.getULX() + (col * cellSize), 
258
                                newBbox.getULY() - (row * cellSize));
259
                p = t.convert(p, p);
260
                p = store.worldToRaster(p);
261
                return p;
262
        }
263
        
264
        /**
265
         * Gets the size of the new image
266
         * @param bbox
267
         * @param newBbox
268
         * @return
269
         */
270
        private double[] getSize(Extent bbox, Extent newBbox) {
271
                double sumSideOldBBox = bbox.width() + bbox.height();
272
                double sumSideNewBBox = newBbox.width() + newBbox.height();
273
                double d1x = (bbox.width() * 100) / sumSideOldBBox; 
274
                double d1y = (bbox.height() * 100) / sumSideOldBBox;
275
                double d2x = (newBbox.width() * 100) / sumSideNewBBox;
276
                double d2y = (newBbox.height() * 100) / sumSideNewBBox;
277
                double p2y = (store.getHeight() * d2y) / d1y;
278
                double p2x = (store.getWidth() * d2x) / d1x;
279
                double newCellSize = newBbox.width() / p2x;
280
                return new double[]{Math.round(p2x), Math.round(p2y), newCellSize};
281
        }
282
        
283
        public boolean export(final String sFilename, Buffer buf, double cellsize, double minX, double minY) {
284

    
285
        try {
286
            RasterManager manager = RasterLocator.getManager();
287
            final DataServerWriter writerBufferServer =
288
                manager.createDataServerWriter();
289
            writerBufferServer.setBuffer(buf, -1);
290
            final Params params = manager.createWriterParams(sFilename);
291
            final AffineTransform affineTransform =
292
                new AffineTransform(cellsize, 0, 0,
293
                    -cellsize, minX, minY);
294

    
295
            final RasterWriter writer =
296
                manager.createWriter(writerBufferServer, sFilename,
297
                    buf.getBandCount(), affineTransform, buf.getWidth(),
298
                    buf.getHeight(), buf.getDataType(), params, null);
299
            writer.dataWrite();
300
            writer.writeClose();
301

    
302
        } catch (final Exception e) {
303
                e.printStackTrace();
304
            return false;
305
        }
306

    
307
        return true;
308

    
309
    }
310

    
311
        /**
312
         * Obtiene el porcentaje de progreso de la tarea de reproyecci?n para
313
         * mostrarlo por pantalla.
314
         * @return
315
         */
316
        public int getPercent() {
317
                return percent;
318
        }
319
}