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 @ 41815

History | View | Annotate | Download (11.7 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.Point2D;
33
import java.awt.geom.Rectangle2D;
34

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

    
44

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

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

    
70
        public Tiling(){}
71

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
216
            int vpCnt = 0;
217

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

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

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

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

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

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

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

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

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

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

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

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

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

    
326

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

    
331
                    vp.setImageSize(auxdim);
332
                    vp.setOffset(new Point2D.Double(tile.getX(), tile.getY()));
333
                     vp.setEnvelope(rectCuadricula);
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