Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_mapcontext / src / org / gvsig / fmap / mapcontext / layers / Tiling.java @ 29277

History | View | Annotate | Download (10.1 KB)

1
/*
2
 * Created on 16-feb-2005
3
 */
4
package org.gvsig.fmap.mapcontext.layers;
5

    
6
import java.awt.Dimension;
7
import java.awt.geom.AffineTransform;
8
import java.awt.geom.NoninvertibleTransformException;
9
import java.awt.geom.Rectangle2D;
10

    
11
import org.gvsig.fmap.geom.GeometryLocator;
12
import org.gvsig.fmap.geom.GeometryManager;
13
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
14
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
15
import org.gvsig.fmap.geom.primitive.Envelope;
16
import org.gvsig.fmap.geom.util.UtilFunctions;
17
import org.gvsig.fmap.mapcontext.ViewPort;
18
import org.slf4j.Logger;
19
import org.slf4j.LoggerFactory;
20

    
21

    
22
/**
23
 * C?lculo de Partes (Tiles) en las que se divide un raster grande.
24
 * Se usa para imprimir rasters y capas raste remotas (WMS).
25
 *
26
 * Para no pedir imagenes demasiado grandes, vamos
27
 * a hacer lo mismo que hace EcwFile: chunkear.
28
 * Llamamos a drawView con cuadraditos m?s peque?os
29
 * del BufferedImage ni caso, cuando se imprime viene con null
30
 * c?digo original de Fran Pe?arrubia
31
 * @author Luis W. Sevilla (sevilla_lui@gva.es)
32
 */
33

    
34
public class Tiling {        
35
        private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
36
        private static final Logger logger = LoggerFactory.getLogger(Tiling.class);
37
        private static final int                MIN_SIZE = 50; //Tama?o m?nimo en pixeles del tile
38
        private boolean                                 debug = true;
39
        private int                                         tileMaxWidth, tileMaxHeight;
40
        private int                                         numRows, numCols;
41
        private double[][]                                 srcPts;
42
        private Rectangle2D[]                         tile;
43
        private double                                         width = 500, height = 500;
44
        private AffineTransform                 mat;
45
        private ViewPort                                 vp;
46

    
47
        public Tiling(){}
48

    
49
        public Tiling(int tileW, int tileH, Rectangle2D r) {
50
                int[] size = this.calcMaxTileSize(tileW, tileH, r);
51
                tileMaxWidth = size[0];
52
                tileMaxHeight = size[1];
53

    
54
        int stepX, stepY;
55
        int xProv, yProv;
56
        int altoAux, anchoAux;
57

    
58
        //Vamos a hacerlo en trozos de AxH
59
        numCols = 1+(int) (r.getWidth()) / tileMaxWidth;
60
        numRows = 1+(int) (r.getHeight()) / tileMaxHeight;
61

    
62
        srcPts = new double[numCols*numRows][8];
63
        tile = new Rectangle2D[numCols*numRows];
64

    
65
            yProv = (int) r.getY();
66
        for (stepY=0; stepY < numRows; stepY++) {
67
                    if ((yProv + tileMaxHeight) > r.getMaxY())
68
                            altoAux = (int) r.getMaxY() - yProv;
69
                    else
70
                            altoAux = tileMaxHeight;
71

    
72
                    xProv = (int) r.getX();
73
                for (stepX=0; stepX < numCols; stepX++) {
74
                            if ((xProv + tileMaxWidth) > r.getMaxX())
75
                                    anchoAux = (int) r.getMaxX() - xProv;
76
                            else
77
                                    anchoAux = tileMaxWidth;
78

    
79
                        //Rectangle newRect = new Rectangle(xProv, yProv, anchoAux, altoAux);
80
                        int tileCnt = stepY*numCols+stepX;
81
                        // Parte que dibuja
82
                        srcPts[tileCnt][0] = xProv;
83
                        srcPts[tileCnt][1] = yProv;
84
                        srcPts[tileCnt][2] = xProv + anchoAux+1;
85
                        srcPts[tileCnt][3] = yProv;
86
                        srcPts[tileCnt][4] = xProv + anchoAux+1;
87
                        srcPts[tileCnt][5] = yProv + altoAux+1;
88
                        srcPts[tileCnt][6] = xProv;
89
                        srcPts[tileCnt][7] = yProv + altoAux+1;
90

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

    
93
                                xProv += tileMaxWidth;
94
                }
95
                yProv += tileMaxHeight;
96
        }
97
        }
98

    
99
        /**
100
         * Calcula el tama?o m?ximo de tile controlando que ning?n tile tenga menos de MIN_SIZE
101
         * pixeles
102
         * @param tileW Ancho del tile
103
         * @param tileH        Alto del tile
104
         * @param r Rectangulo que define el area de la imagen
105
         */
106
        public int[] calcMaxTileSize(int tileW, int tileH, Rectangle2D r){
107
                
108
                if(r.getWidth() < tileW || r.getHeight() < tileH){
109
                        int[] sizeTiles = {tileW, tileH};
110
                        return sizeTiles;
111
                }
112

    
113
        int wLastCol = 0;
114
        tileW += MIN_SIZE;
115
                do{
116
                        tileW -= MIN_SIZE;
117
                int numCols = (int) (r.getWidth() / tileW);
118
                int w = 0;
119
                for(int i = 0; i < numCols; i++)
120
                        w += tileW;
121
                wLastCol = ((int) r.getWidth()) - w;
122
                }while(wLastCol < MIN_SIZE && tileW > (MIN_SIZE * 2));
123

    
124
                int hLastRow = 0;
125
        tileH += MIN_SIZE;
126
                do{
127
                        tileH -= MIN_SIZE;
128
                int numRows = (int) (r.getHeight() / tileH);
129
                int h = 0;
130
                for(int i = 0; i < numRows; i++)
131
                        h += tileH;
132
                hLastRow = ((int) r.getHeight()) - h;
133
                }while(hLastRow < MIN_SIZE && tileH > (MIN_SIZE * 2));
134

    
135
                tileMaxWidth = tileW;
136
                tileMaxHeight = tileH;
137
                int[] sizeTiles = {tileMaxWidth, tileMaxHeight};
138
                return sizeTiles;
139
        }
140

    
141
        public double [] getTilePts(int colNr, int rowNr) {
142
                return srcPts[rowNr*numCols+colNr];
143
        }
144

    
145
        public double [] getTilePts(int num) {
146
                return srcPts[num];
147
        }
148

    
149
        public Rectangle2D getTileSz(int colNr, int rowNr) {
150
                return tile[rowNr*numCols+colNr];
151
        }
152

    
153
        public Rectangle2D getTile(int num) {
154
                return tile[num];
155
        }
156

    
157
        /**
158
         * @return Returns the numCols.
159
         */
160
        public int getNumCols() {
161
                return numCols;
162
        }
163
        /**
164
         * @return Returns the numRows.
165
         */
166
        public int getNumRows() {
167
                return numRows;
168
        }
169

    
170
        public int getNumTiles() { return numRows*numCols; }
171
        /**
172
         * @return Returns the tileHeight.
173
         */
174
        public int getMaxTileHeight() {
175
                return tileMaxHeight;
176
        }
177
        /**
178
         * @return Returns the tileWidth.
179
         */
180
        public int getMaxTileWidth() {
181
                return tileMaxWidth;
182
        }
183

    
184
        ViewPort[] viewPortList = null;
185
        private void calcViewPort(ViewPort viewPort)throws NoninvertibleTransformException{
186
                viewPortList = new ViewPort[numCols*numRows];
187

    
188
                /*if(viewPort.getImageWidth() < width && viewPort.getImageHeight() < height){
189
                        viewPortList[0] = viewPort;
190
                        return;
191
                }*/
192

    
193
            int vpCnt = 0;
194

    
195
            double imgPxX = viewPort.getImageWidth();
196
            double dWcX = viewPort.getAdjustedExtent().getLength(0);
197
            double tileWcW = (getTile(vpCnt).getWidth() * dWcX) / imgPxX;
198

    
199
            double imgPxY = viewPort.getImageHeight();
200
            double dWcY = viewPort.getAdjustedExtent().getLength(1);
201
            double tileWcH = (getTile(vpCnt).getHeight() * dWcY) / imgPxY;
202

    
203
            viewPortList[0] = viewPort.cloneViewPort();
204
            
205
            int auxw = (int) getTile(vpCnt).getWidth();
206
            int auxh = (int) getTile(vpCnt).getHeight();
207
            Dimension auxdim = new Dimension(auxw, auxh);
208
            
209
            viewPortList[0].setImageSize(auxdim);
210
            Envelope r=viewPort.getAdjustedExtent();
211
            try {
212
                        viewPortList[0].setEnvelope(geomManager.createEnvelope(r.getMinimum(0), r.getMaximum(1) - tileWcH,r.getMinimum(0)+tileWcW, r.getMaximum(1), SUBTYPES.GEOM2D));
213
                } catch (CreateEnvelopeException e) {
214
                        logger.error("Error setting the envelope", e);
215
                        e.printStackTrace();
216
                }
217
            viewPortList[0].setAffineTransform(mat);
218

    
219
            double wt = tileWcW;
220
            double ht = tileWcH;
221
            double xt = viewPort.getAdjustedExtent().getMinimum(0);
222
            double yt = viewPort.getAdjustedExtent().getMaximum(1) - tileWcH;
223

    
224
            for (int stepY=0; stepY < numRows; stepY++) {
225
                    wt = tileWcW;
226
                    xt = viewPort.getAdjustedExtent().getMinimum(0);
227
                    for (int stepX=0; stepX < numCols; stepX++) {
228
                            vpCnt = stepY*numCols+stepX;
229
                            if(vpCnt > 0){
230
                                    if(stepX > 0)
231
                                            xt += wt;
232
                                    if((xt + wt) > viewPort.getAdjustedExtent().getMaximum(0))
233
                                            wt = Math.abs(viewPort.getAdjustedExtent().getMaximum(0) - xt);
234

    
235
                                    viewPortList[vpCnt] = viewPort.cloneViewPort();
236
                                    
237
                                auxw = (int) getTile(vpCnt).getWidth();
238
                                auxh = (int) getTile(vpCnt).getHeight();
239
                                auxdim = new Dimension(auxw, auxh);
240

    
241
                                    viewPortList[vpCnt].setImageSize(auxdim);
242
                                    
243
                                    try {
244
                                                viewPortList[vpCnt].setEnvelope(geomManager.createEnvelope(xt, yt,xt + wt, yt + ht, SUBTYPES.GEOM2D));
245
                                        } catch (CreateEnvelopeException e) {
246
                                                logger.error("Error setting the envelope", e);
247
                                                e.printStackTrace();
248
                                        }
249
                                    viewPortList[vpCnt].setAffineTransform(mat);
250

    
251
                            }
252
                            //System.out.println("ViewPort: "+vpCnt+" "+viewPortList[vpCnt].getAdjustedExtent()+" "+getTile(vpCnt).getSize());
253
                    }
254
                    if((yt - ht) < viewPort.getAdjustedExtent().getMinimum(1)){
255
                            ht = Math.abs(yt - viewPort.getAdjustedExtent().getMinimum(1));
256
                            yt = viewPort.getAdjustedExtent().getMinimum(1);
257
                    }else
258
                            yt -= ht;
259
            }
260
        }
261

    
262
        public ViewPort getTileViewPort(ViewPort viewPort, int tileNr) throws NoninvertibleTransformException {
263
                /*if(viewPortList == null)
264
                        this.calcViewPort(viewPort);
265
                return viewPortList[tileNr];*/
266

    
267
                if(tile.length == 1)
268
                        return viewPort;
269

    
270
                double [] dstPts = new double[8];
271
                double [] srcPts = getTilePts(tileNr);
272
                Rectangle2D tile = getTile(tileNr);
273
                //Rectangle newRect = new Rectangle((int)srcPts[0], (int)srcPts[1], tileSz[0], tileSz[1]);
274

    
275
                mat.inverseTransform(srcPts, 0, dstPts, 0, 4);
276
                double x = dstPts[0], w = dstPts[2] - dstPts[0];
277
                double y = dstPts[1], h = dstPts[5] - dstPts[3];
278
                if (w < 0) { x = dstPts[2]; w = dstPts[0] - dstPts[2]; }
279
                if (h < 0) { y = dstPts[5]; h = dstPts[3] - dstPts[5]; }
280
                Envelope rectCuadricula = null;
281
                try {
282
                        rectCuadricula = geomManager.createEnvelope(x, y,x+ w,y+ h, SUBTYPES.GEOM2D);
283
                } catch (CreateEnvelopeException e) {
284
                        logger.error("Error setting the envelope", e);
285
                        e.printStackTrace();
286
                }
287
                //Extent extent = new Extent(rectCuadricula);
288

    
289
                ViewPort vp = viewPort.cloneViewPort();
290
                
291
                
292
            int auxw = (int) tile.getWidth();
293
            int auxh = (int) tile.getHeight();
294
            Dimension auxdim = new Dimension(auxw, auxh);
295

    
296
                vp.setImageSize(auxdim);
297
                //vp.setOffset(tile.getLocation());
298
                vp.setEnvelope(rectCuadricula);
299
                vp.setAffineTransform(mat);
300

    
301
                if (debug)
302
                    System.out.println("Tiling.print(): tile "+tileNr+" de "
303
                            + getNumTiles() +
304
                            "\n, Extent = "+vp.getAdjustedExtent() + " tile: "
305
                            + tile);
306

    
307
                return vp;
308
        }
309
        /**
310
         * @return Returns the mat.
311
         */
312
        public AffineTransform getAffineTransform() {
313
                return mat;
314
        }
315
        /**
316
         * @param mat The mat to set.
317
         */
318
        public void setAffineTransform(AffineTransform mat) {
319
                this.mat = mat;
320
        }
321
        /**
322
         * @return Returns the debug.
323
         */
324
        public boolean isDebug() {
325
                return debug;
326
        }
327
        /**
328
         * @param debug The debug to set.
329
         */
330
        public void setDebug(boolean debug) {
331
                this.debug = debug;
332
        }
333
}
334

    
335