Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.mapcontext / org.gvsig.fmap.mapcontext.api / src / main / java / org / gvsig / fmap / mapcontext / layers / Tiling.java @ 40559

History | View | Annotate | Download (11.6 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
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 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
/*
25
 * Created on 16-feb-2005
26
 */
27
package org.gvsig.fmap.mapcontext.layers;
28

    
29
import java.awt.Dimension;
30
import java.awt.geom.AffineTransform;
31
import java.awt.geom.NoninvertibleTransformException;
32
import java.awt.geom.Rectangle2D;
33

    
34
import org.gvsig.fmap.geom.GeometryLocator;
35
import org.gvsig.fmap.geom.GeometryManager;
36
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
37
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
38
import org.gvsig.fmap.geom.primitive.Envelope;
39
import org.gvsig.fmap.mapcontext.ViewPort;
40
import org.slf4j.Logger;
41
import org.slf4j.LoggerFactory;
42

    
43

    
44
/**
45
 * C?lculo de Partes (Tiles) en las que se divide un raster grande.
46
 * Se usa para imprimir rasters y capas raste remotas (WMS).
47
 *
48
 * Para no pedir imagenes demasiado grandes, vamos
49
 * a hacer lo mismo que hace EcwFile: chunkear.
50
 * Llamamos a drawView con cuadraditos m?s peque?os
51
 * del BufferedImage ni caso, cuando se imprime viene con null
52
 * c?digo original de Fran Pe?arrubia
53
 * @author Luis W. Sevilla (sevilla_lui@gva.es)
54
 */
55

    
56
public class Tiling {        
57
        private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
58
        private static final Logger logger = LoggerFactory.getLogger(Tiling.class);
59
        private static final int                MIN_SIZE = 50; //Tama?o m?nimo en pixeles del tile
60
        private boolean                                 debug = true;
61
        private int                                         tileMaxWidth, tileMaxHeight;
62
        private int                                         numRows, numCols;
63
        private double[][]                                 srcPts;
64
        private Rectangle2D[]                         tile;
65
        private double                                         width = 500, height = 500;
66
        private AffineTransform                 mat;
67
        private ViewPort                                 vp;
68

    
69
        public Tiling(){}
70

    
71
        public Tiling(int tileW, int tileH, Rectangle2D r) {
72
                int[] size = this.calcMaxTileSize(tileW, tileH, r);
73
                tileMaxWidth = size[0];
74
                tileMaxHeight = size[1];
75

    
76
        int stepX, stepY;
77
        int xProv, yProv;
78
        int altoAux, anchoAux;
79

    
80
        //Vamos a hacerlo en trozos de AxH
81
        numCols = 1+(int) (r.getWidth()) / tileMaxWidth;
82
        numRows = 1+(int) (r.getHeight()) / tileMaxHeight;
83

    
84
        srcPts = new double[numCols*numRows][8];
85
        tile = new Rectangle2D[numCols*numRows];
86

    
87
            yProv = (int) r.getY();
88
        for (stepY=0; stepY < numRows; stepY++) {
89
                    if ((yProv + tileMaxHeight) > r.getMaxY())
90
                            altoAux = (int) r.getMaxY() - yProv;
91
                    else
92
                            altoAux = tileMaxHeight;
93

    
94
                    xProv = (int) r.getX();
95
                for (stepX=0; stepX < numCols; stepX++) {
96
                            if ((xProv + tileMaxWidth) > r.getMaxX())
97
                                    anchoAux = (int) r.getMaxX() - xProv;
98
                            else
99
                                    anchoAux = tileMaxWidth;
100

    
101
                        //Rectangle newRect = new Rectangle(xProv, yProv, anchoAux, altoAux);
102
                        int tileCnt = stepY*numCols+stepX;
103
                        // Parte que dibuja
104
                        srcPts[tileCnt][0] = xProv;
105
                        srcPts[tileCnt][1] = yProv;
106
                        srcPts[tileCnt][2] = xProv + anchoAux+1;
107
                        srcPts[tileCnt][3] = yProv;
108
                        srcPts[tileCnt][4] = xProv + anchoAux+1;
109
                        srcPts[tileCnt][5] = yProv + altoAux+1;
110
                        srcPts[tileCnt][6] = xProv;
111
                        srcPts[tileCnt][7] = yProv + altoAux+1;
112

    
113
                        tile[tileCnt] = new Rectangle2D.Float(xProv, yProv, anchoAux+1, altoAux+1);
114

    
115
                                xProv += tileMaxWidth;
116
                }
117
                yProv += tileMaxHeight;
118
        }
119
        }
120

    
121
        /**
122
         * Calcula el tama?o m?ximo de tile controlando que ning?n tile tenga menos de MIN_SIZE
123
         * pixeles
124
         * @param tileW Ancho del tile
125
         * @param tileH        Alto del tile
126
         * @param r Rectangulo que define el area de la imagen
127
         */
128
        public int[] calcMaxTileSize(int tileW, int tileH, Rectangle2D r){
129
                
130
                if(r.getWidth() < tileW || r.getHeight() < tileH){
131
                        int[] sizeTiles = {tileW, tileH};
132
                        return sizeTiles;
133
                }
134

    
135
        int wLastCol = 0;
136
        tileW += MIN_SIZE;
137
                do{
138
                        tileW -= MIN_SIZE;
139
                int numCols = (int) (r.getWidth() / tileW);
140
                int w = 0;
141
                for(int i = 0; i < numCols; i++)
142
                        w += tileW;
143
                wLastCol = ((int) r.getWidth()) - w;
144
                }while(wLastCol < MIN_SIZE && tileW > (MIN_SIZE * 2));
145

    
146
                int hLastRow = 0;
147
        tileH += MIN_SIZE;
148
                do{
149
                        tileH -= MIN_SIZE;
150
                int numRows = (int) (r.getHeight() / tileH);
151
                int h = 0;
152
                for(int i = 0; i < numRows; i++)
153
                        h += tileH;
154
                hLastRow = ((int) r.getHeight()) - h;
155
                }while(hLastRow < MIN_SIZE && tileH > (MIN_SIZE * 2));
156

    
157
                tileMaxWidth = tileW;
158
                tileMaxHeight = tileH;
159
                int[] sizeTiles = {tileMaxWidth, tileMaxHeight};
160
                return sizeTiles;
161
        }
162

    
163
        public double [] getTilePts(int colNr, int rowNr) {
164
                return srcPts[rowNr*numCols+colNr];
165
        }
166

    
167
        public double [] getTilePts(int num) {
168
                return srcPts[num];
169
        }
170

    
171
        public Rectangle2D getTileSz(int colNr, int rowNr) {
172
                return tile[rowNr*numCols+colNr];
173
        }
174

    
175
        public Rectangle2D getTile(int num) {
176
                return tile[num];
177
        }
178

    
179
        /**
180
         * @return Returns the numCols.
181
         */
182
        public int getNumCols() {
183
                return numCols;
184
        }
185
        /**
186
         * @return Returns the numRows.
187
         */
188
        public int getNumRows() {
189
                return numRows;
190
        }
191

    
192
        public int getNumTiles() { return numRows*numCols; }
193
        /**
194
         * @return Returns the tileHeight.
195
         */
196
        public int getMaxTileHeight() {
197
                return tileMaxHeight;
198
        }
199
        /**
200
         * @return Returns the tileWidth.
201
         */
202
        public int getMaxTileWidth() {
203
                return tileMaxWidth;
204
        }
205

    
206
        ViewPort[] viewPortList = null;
207
        private void calcViewPort(ViewPort viewPort)throws NoninvertibleTransformException{
208
                viewPortList = new ViewPort[numCols*numRows];
209

    
210
                /*if(viewPort.getImageWidth() < width && viewPort.getImageHeight() < height){
211
                        viewPortList[0] = viewPort;
212
                        return;
213
                }*/
214

    
215
            int vpCnt = 0;
216

    
217
            double imgPxX = viewPort.getImageWidth();
218
            double dWcX = viewPort.getAdjustedExtent().getLength(0);
219
            double tileWcW = (getTile(vpCnt).getWidth() * dWcX) / imgPxX;
220

    
221
            double imgPxY = viewPort.getImageHeight();
222
            double dWcY = viewPort.getAdjustedExtent().getLength(1);
223
            double tileWcH = (getTile(vpCnt).getHeight() * dWcY) / imgPxY;
224

    
225
            try {
226
            viewPortList[0] = (ViewPort) viewPort.clone();
227
        } catch (CloneNotSupportedException e) {
228
            logger.error("Error clonning the viewport", e);
229
            e.printStackTrace();
230
        }
231
            
232
            int auxw = (int) getTile(vpCnt).getWidth();
233
            int auxh = (int) getTile(vpCnt).getHeight();
234
            Dimension auxdim = new Dimension(auxw, auxh);
235
            
236
            viewPortList[0].setImageSize(auxdim);
237
            Envelope r=viewPort.getAdjustedExtent();
238
            try {
239
                        viewPortList[0].setEnvelope(geomManager.createEnvelope(r.getMinimum(0), r.getMaximum(1) - tileWcH,r.getMinimum(0)+tileWcW, r.getMaximum(1), SUBTYPES.GEOM2D));
240
                } catch (CreateEnvelopeException e) {
241
                        logger.error("Error setting the envelope", e);
242
                        e.printStackTrace();
243
                }
244
            viewPortList[0].setAffineTransform(mat);
245

    
246
            double wt = tileWcW;
247
            double ht = tileWcH;
248
            double xt = viewPort.getAdjustedExtent().getMinimum(0);
249
            double yt = viewPort.getAdjustedExtent().getMaximum(1) - tileWcH;
250

    
251
            for (int stepY=0; stepY < numRows; stepY++) {
252
                    wt = tileWcW;
253
                    xt = viewPort.getAdjustedExtent().getMinimum(0);
254
                    for (int stepX=0; stepX < numCols; stepX++) {
255
                            vpCnt = stepY*numCols+stepX;
256
                            if(vpCnt > 0){
257
                                    if(stepX > 0)
258
                                            xt += wt;
259
                                    if((xt + wt) > viewPort.getAdjustedExtent().getMaximum(0))
260
                                            wt = Math.abs(viewPort.getAdjustedExtent().getMaximum(0) - xt);
261

    
262
                                    try {
263
                        viewPortList[vpCnt] = (ViewPort) viewPort.clone();
264
                    } catch (CloneNotSupportedException e) {
265
                        logger.error("Error clonning the viewport", e);
266
                        e.printStackTrace();
267
                    }
268
                                    
269
                                auxw = (int) getTile(vpCnt).getWidth();
270
                                auxh = (int) getTile(vpCnt).getHeight();
271
                                auxdim = new Dimension(auxw, auxh);
272

    
273
                                    viewPortList[vpCnt].setImageSize(auxdim);
274
                                    
275
                                    try {
276
                                                viewPortList[vpCnt].setEnvelope(geomManager.createEnvelope(xt, yt,xt + wt, yt + ht, SUBTYPES.GEOM2D));
277
                                        } catch (CreateEnvelopeException e) {
278
                                                logger.error("Error setting the envelope", e);
279
                                                e.printStackTrace();
280
                                        }
281
                                    viewPortList[vpCnt].setAffineTransform(mat);
282

    
283
                            }
284
                            //System.out.println("ViewPort: "+vpCnt+" "+viewPortList[vpCnt].getAdjustedExtent()+" "+getTile(vpCnt).getSize());
285
                    }
286
                    if((yt - ht) < viewPort.getAdjustedExtent().getMinimum(1)){
287
                            ht = Math.abs(yt - viewPort.getAdjustedExtent().getMinimum(1));
288
                            yt = viewPort.getAdjustedExtent().getMinimum(1);
289
                    }else
290
                            yt -= ht;
291
            }
292
        }
293

    
294
        public ViewPort getTileViewPort(ViewPort viewPort, int tileNr) throws NoninvertibleTransformException {
295
                /*if(viewPortList == null)
296
                        this.calcViewPort(viewPort);
297
                return viewPortList[tileNr];*/
298

    
299
                if(tile.length == 1)
300
                        return viewPort;
301

    
302
                double [] dstPts = new double[8];
303
                double [] srcPts = getTilePts(tileNr);
304
                Rectangle2D tile = getTile(tileNr);
305
                //Rectangle newRect = new Rectangle((int)srcPts[0], (int)srcPts[1], tileSz[0], tileSz[1]);
306

    
307
                mat.inverseTransform(srcPts, 0, dstPts, 0, 4);
308
                double x = dstPts[0], w = dstPts[2] - dstPts[0];
309
                double y = dstPts[1], h = dstPts[5] - dstPts[3];
310
                if (w < 0) { x = dstPts[2]; w = dstPts[0] - dstPts[2]; }
311
                if (h < 0) { y = dstPts[5]; h = dstPts[3] - dstPts[5]; }
312
                Envelope rectCuadricula = null;
313
                try {
314
                        rectCuadricula = geomManager.createEnvelope(x, y,x+ w,y+ h, SUBTYPES.GEOM2D);
315
                } catch (CreateEnvelopeException e) {
316
                        logger.error("Error setting the envelope", e);
317
                        e.printStackTrace();
318
                }
319
                //Extent extent = new Extent(rectCuadricula);
320

    
321
                ViewPort vp = null;
322
                try {
323
                    vp = (ViewPort) viewPort.clone();
324

    
325

    
326
                    int auxw = (int) tile.getWidth();
327
                    int auxh = (int) tile.getHeight();
328
                    Dimension auxdim = new Dimension(auxw, auxh);
329

    
330
                    vp.setImageSize(auxdim);
331
                    //vp.setOffset(tile.getLocation());
332
                    vp.setEnvelope(rectCuadricula);
333
                    vp.setAffineTransform(mat);
334

    
335
                    if (debug)
336
                        System.out.println("Tiling.print(): tile "+tileNr+" de "
337
                            + getNumTiles() +
338
                            "\n, Extent = "+vp.getAdjustedExtent() + " tile: "
339
                            + tile);
340

    
341
                } catch (CloneNotSupportedException e) {
342
            logger.error("Error clonning the viewport", e);
343
            e.printStackTrace();
344
        }
345
        return vp;
346
        }
347
        /**
348
         * @return Returns the mat.
349
         */
350
        public AffineTransform getAffineTransform() {
351
                return mat;
352
        }
353
        /**
354
         * @param mat The mat to set.
355
         */
356
        public void setAffineTransform(AffineTransform mat) {
357
                this.mat = mat;
358
        }
359
        /**
360
         * @return Returns the debug.
361
         */
362
        public boolean isDebug() {
363
                return debug;
364
        }
365
        /**
366
         * @param debug The debug to set.
367
         */
368
        public void setDebug(boolean debug) {
369
                this.debug = debug;
370
        }
371
}
372

    
373