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 | 40559 | jjdelcerro | /**
|
---|---|---|---|
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 | 40435 | jjdelcerro | /*
|
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 |