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 @ 44455
History | View | Annotate | Download (11.7 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 | 41815 | jjdelcerro | import java.awt.geom.Point2D; |
33 | 40435 | jjdelcerro | 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 | 41815 | jjdelcerro | vp.setOffset(new Point2D.Double(tile.getX(), tile.getY())); |
333 | vp.setEnvelope(rectCuadricula); |
||
334 | 40435 | jjdelcerro | |
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 |