gvsig-raster / org.gvsig.raster / branches / org.gvsig.raster.2.4 / org.gvsig.wmts / org.gvsig.wmts.provider / src / main / java / org / gvsig / wmts / provider / WMTSRasterProvider.java @ 8842
History | View | Annotate | Download (35.9 KB)
1 | 8700 | fdiaz | /* gvSIG. Desktop Geographic Information System.
|
---|---|---|---|
2 | *
|
||
3 | * Copyright ? 2007-2018 gvSIG Association
|
||
4 | *
|
||
5 | * This program is free software; you can redistribute it and/or
|
||
6 | * modify it under the terms of the GNU General Public License
|
||
7 | * as published by the Free Software Foundation; either version 2
|
||
8 | * of the License, or (at your option) any later version.
|
||
9 | *
|
||
10 | * This program is distributed in the hope that it will be useful,
|
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
13 | * GNU General Public License for more details.
|
||
14 | *
|
||
15 | * You should have received a copy of the GNU General Public License
|
||
16 | * along with this program; if not, write to the Free Software
|
||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||
18 | * MA 02110-1301, USA.
|
||
19 | *
|
||
20 | * For any additional information, do not hesitate to contact us
|
||
21 | * at info AT gvsig.com, or visit our website www.gvsig.com.
|
||
22 | */
|
||
23 | 6532 | fdiaz | package org.gvsig.wmts.provider; |
24 | |||
25 | 6551 | fdiaz | import java.awt.Image; |
26 | 6532 | fdiaz | import java.awt.geom.Rectangle2D; |
27 | import java.awt.image.BufferedImage; |
||
28 | import java.io.File; |
||
29 | import java.io.IOException; |
||
30 | import java.net.URL; |
||
31 | import java.util.ArrayList; |
||
32 | 8700 | fdiaz | import java.util.Collections; |
33 | 6532 | fdiaz | import java.util.HashMap; |
34 | 6533 | fdiaz | import java.util.Iterator; |
35 | 6532 | fdiaz | import java.util.List; |
36 | import java.util.Map; |
||
37 | 8842 | fdiaz | import java.util.Set; |
38 | 8700 | fdiaz | import java.util.SortedSet; |
39 | import java.util.TreeSet; |
||
40 | 6535 | fdiaz | import java.util.Map.Entry; |
41 | 6532 | fdiaz | |
42 | import javax.imageio.ImageIO; |
||
43 | |||
44 | 6535 | fdiaz | import org.cresques.cts.ICoordTrans; |
45 | 6532 | fdiaz | import org.cresques.cts.IProjection; |
46 | import org.slf4j.Logger; |
||
47 | import org.slf4j.LoggerFactory; |
||
48 | |||
49 | 6535 | fdiaz | import org.gvsig.fmap.crs.CRSFactory; |
50 | 6532 | fdiaz | import org.gvsig.fmap.dal.DALLocator; |
51 | import org.gvsig.fmap.dal.DataManager; |
||
52 | import org.gvsig.fmap.dal.DataServerExplorer; |
||
53 | import org.gvsig.fmap.dal.DataServerExplorerParameters; |
||
54 | import org.gvsig.fmap.dal.DataStore; |
||
55 | import org.gvsig.fmap.dal.DataStoreParameters; |
||
56 | import org.gvsig.fmap.dal.FileHelper; |
||
57 | import org.gvsig.fmap.dal.exception.DataException; |
||
58 | import org.gvsig.fmap.dal.exception.InitializeException; |
||
59 | import org.gvsig.fmap.dal.exception.OpenException; |
||
60 | import org.gvsig.fmap.dal.exception.ReadException; |
||
61 | import org.gvsig.fmap.dal.exception.ValidateDataParametersException; |
||
62 | import org.gvsig.fmap.dal.raster.api.BandQuery; |
||
63 | import org.gvsig.fmap.dal.raster.api.RasterQuery; |
||
64 | import org.gvsig.fmap.dal.raster.spi.AbstractRasterStoreProvider; |
||
65 | 6667 | fdiaz | import org.gvsig.fmap.dal.raster.spi.BandDescriptorServices; |
66 | 6532 | fdiaz | import org.gvsig.fmap.dal.resource.spi.ResourceProvider; |
67 | import org.gvsig.fmap.dal.spi.DataStoreProviderServices; |
||
68 | 6535 | fdiaz | import org.gvsig.fmap.geom.Geometry; |
69 | 6532 | fdiaz | import org.gvsig.fmap.geom.Geometry.DIMENSIONS; |
70 | import org.gvsig.fmap.geom.GeometryLocator; |
||
71 | import org.gvsig.fmap.geom.GeometryManager; |
||
72 | import org.gvsig.fmap.geom.exception.CreateEnvelopeException; |
||
73 | import org.gvsig.fmap.geom.primitive.Envelope; |
||
74 | import org.gvsig.metadata.MetadataLocator; |
||
75 | import org.gvsig.metadata.MetadataManager; |
||
76 | import org.gvsig.metadata.exceptions.MetadataException; |
||
77 | import org.gvsig.raster.lib.buffer.api.Buffer; |
||
78 | 6682 | fdiaz | import org.gvsig.raster.lib.buffer.api.BufferDimensions; |
79 | 6532 | fdiaz | import org.gvsig.raster.lib.buffer.api.BufferLocator; |
80 | import org.gvsig.raster.lib.buffer.api.BufferManager; |
||
81 | import org.gvsig.raster.lib.buffer.api.NoData; |
||
82 | import org.gvsig.raster.lib.buffer.api.PageManager; |
||
83 | import org.gvsig.raster.lib.buffer.api.TileStruct; |
||
84 | import org.gvsig.raster.lib.buffer.api.exceptions.BufferException; |
||
85 | import org.gvsig.raster.lib.buffer.spi.DefaultTileStruct; |
||
86 | import org.gvsig.raster.wmts.ogc.WMTSClient; |
||
87 | import org.gvsig.raster.wmts.ogc.WMTSOGCLocator; |
||
88 | import org.gvsig.raster.wmts.ogc.WMTSStatus; |
||
89 | 6551 | fdiaz | import org.gvsig.raster.wmts.ogc.exception.WMTSException; |
90 | 6533 | fdiaz | import org.gvsig.raster.wmts.ogc.struct.WMTSLayer; |
91 | 6551 | fdiaz | import org.gvsig.raster.wmts.ogc.struct.WMTSStyle; |
92 | 6533 | fdiaz | import org.gvsig.raster.wmts.ogc.struct.WMTSTileMatrix; |
93 | import org.gvsig.raster.wmts.ogc.struct.WMTSTileMatrixSet; |
||
94 | 6667 | fdiaz | import org.gvsig.tools.dataTypes.DataTypes; |
95 | 8842 | fdiaz | import org.gvsig.tools.dispose.Disposable; |
96 | 6535 | fdiaz | import org.gvsig.tools.dispose.DisposeUtils; |
97 | 6532 | fdiaz | import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException; |
98 | 8842 | fdiaz | import org.gvsig.tools.exception.BaseException; |
99 | 6532 | fdiaz | import org.gvsig.tools.locator.LocatorException; |
100 | |||
101 | /**
|
||
102 | * @author fdiaz
|
||
103 | *
|
||
104 | */
|
||
105 | public class WMTSRasterProvider extends AbstractRasterStoreProvider { |
||
106 | |||
107 | private static final Logger logger = LoggerFactory.getLogger(WMTSRasterProvider.class); |
||
108 | |||
109 | 8700 | fdiaz | public static String NAME = "WMTS"; |
110 | 6532 | fdiaz | public static String DESCRIPTION = "WMTS Raster Provider"; |
111 | 8700 | fdiaz | public static final String METADATA_DEFINITION_NAME = "WMTS"; |
112 | 6532 | fdiaz | |
113 | public static final int DEFAULT_BUFFER_SIZE = 256; |
||
114 | 8700 | fdiaz | public static final int DEFAULT_MAX_ZOOM_LEVEL = 22; |
115 | 6532 | fdiaz | |
116 | // WMTS Parameters
|
||
117 | private WMTSClient wmtsClient;
|
||
118 | private WMTSStatus wmtsStatus;
|
||
119 | 6535 | fdiaz | private String layerName; |
120 | 6532 | fdiaz | |
121 | private Envelope envelope = null; |
||
122 | |||
123 | private IProjection projection = null; |
||
124 | |||
125 | private WMTSImage image;
|
||
126 | 6535 | fdiaz | private TileStruct tileStruct = null; |
127 | private Map<Integer,List<PageManager>> pageManagersPerZoomLevel = null; |
||
128 | private Map<Integer, WMTSTileMatrix> tileMatrixPerZoomLevel = null; |
||
129 | private int columnsPerTile; |
||
130 | private int rowsPerTile; |
||
131 | 6532 | fdiaz | |
132 | 8700 | fdiaz | private int maxZoomLevel; |
133 | |||
134 | 6532 | fdiaz | protected WMTSRasterProvider(DataStoreParameters params, DataStoreProviderServices storeServices) throws InitializeException { |
135 | super(params, storeServices, FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME));
|
||
136 | initParams(); |
||
137 | } |
||
138 | |||
139 | private void initParams() throws InitializeException { |
||
140 | WMTSRasterProviderParameters parameters = (WMTSRasterProviderParameters) getParameters(); |
||
141 | 6535 | fdiaz | pageManagersPerZoomLevel = new HashMap<Integer, List<PageManager>>(); |
142 | 8842 | fdiaz | |
143 | 6535 | fdiaz | envelope = getEnvelope(); |
144 | 8700 | fdiaz | maxZoomLevel = DEFAULT_MAX_ZOOM_LEVEL; |
145 | 6532 | fdiaz | |
146 | 6535 | fdiaz | } |
147 | 6532 | fdiaz | |
148 | 6535 | fdiaz | protected WMTSStatus getWMTSStatus() throws InitializeException { |
149 | if( this.wmtsStatus == null ){ |
||
150 | wmtsStatus = getWMTSClient().createStatus(); |
||
151 | 6532 | fdiaz | |
152 | 6535 | fdiaz | WMTSLayer wmtsLayer = getWMTSClient().getLayer(getLayerName()); |
153 | wmtsStatus.setLayer(wmtsLayer.getIdentifier()); |
||
154 | 6532 | fdiaz | |
155 | 6535 | fdiaz | wmtsStatus.setStyle((String)getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_STYLE_PARAMETER_NAME));
|
156 | wmtsStatus.setFormat((String) getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_FORMAT_PARAMETER_NAME));
|
||
157 | wmtsStatus.setInfoFormat((String) getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_INFO_FORMAT_PARAMETER_NAME));
|
||
158 | wmtsStatus.setSrs(getProjection().getAbrev()); |
||
159 | 6532 | fdiaz | |
160 | 6535 | fdiaz | wmtsStatus.setTileMatrixSet(getTileMatrixSet().getIdentifier()); |
161 | 6532 | fdiaz | |
162 | |||
163 | 6535 | fdiaz | } |
164 | // TODO Auto-generated method stub
|
||
165 | return this.wmtsStatus; |
||
166 | } |
||
167 | 6533 | fdiaz | |
168 | 6535 | fdiaz | private String getLayerName() { |
169 | if( this.layerName == null){ |
||
170 | this.layerName = (String) getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_LAYER_PARAMETER_NAME); |
||
171 | } |
||
172 | return this.layerName; |
||
173 | 6532 | fdiaz | } |
174 | |||
175 | protected static void registerMetadataDefinition() throws MetadataException { |
||
176 | MetadataManager manager = MetadataLocator.getMetadataManager(); |
||
177 | if (manager.getDefinition(METADATA_DEFINITION_NAME) == null) { |
||
178 | manager.addDefinition(METADATA_DEFINITION_NAME, |
||
179 | WMTSRasterProviderParameters.class.getResourceAsStream("WMTSRasterMetadata.xml"),
|
||
180 | WMTSRasterProviderParameters.class.getClassLoader()); |
||
181 | } |
||
182 | } |
||
183 | |||
184 | @Override
|
||
185 | public Buffer createBuffer(RasterQuery rasterQuery) throws BufferException { |
||
186 | |||
187 | 6535 | fdiaz | try {
|
188 | BufferManager bufferManager = BufferLocator.getBufferManager(); |
||
189 | int[] bandDataTypes; |
||
190 | List<PageManager> pageManagers = new ArrayList<PageManager>(); |
||
191 | NoData[] bandNoData;
|
||
192 | Envelope envelope = getTileStruct().getEnvelope(); |
||
193 | double pixelSize = rasterQuery.getPixelSize();
|
||
194 | int zoomLevel;
|
||
195 | if (pixelSize == 0) { |
||
196 | zoomLevel = 0;
|
||
197 | } else {
|
||
198 | zoomLevel = getZoomLvlForPixelSize(pixelSize); |
||
199 | } |
||
200 | 6532 | fdiaz | |
201 | 6535 | fdiaz | if (!rasterQuery.getBands().isEmpty()) {
|
202 | List<BandQuery> bands;
|
||
203 | bands = rasterQuery.getBands(); |
||
204 | bandDataTypes = new int[bands.size()]; |
||
205 | bandNoData = new NoData[bands.size()];
|
||
206 | 6532 | fdiaz | |
207 | 6535 | fdiaz | for (BandQuery bandQuery : bands) {
|
208 | int band = bandQuery.getBand();
|
||
209 | 6667 | fdiaz | bandDataTypes[band] = this.getBandDescriptor(band).getDataType();
|
210 | bandNoData[band] = this.getNoData(rasterQuery, band);
|
||
211 | 6535 | fdiaz | try {
|
212 | pageManagers.add(getPageManagersInZoom(zoomLevel).get(band)); |
||
213 | } catch (ValidateDataParametersException | CreateEnvelopeException | DataException
|
||
214 | | CloneNotSupportedException e) {
|
||
215 | // TODO Auto-generated catch block
|
||
216 | throw new BufferException(e); |
||
217 | } |
||
218 | } |
||
219 | } else {
|
||
220 | int bands = getBands();
|
||
221 | bandDataTypes = new int[bands]; |
||
222 | bandNoData = new NoData[bands];
|
||
223 | for (int i = 0; i < bands; i++) { |
||
224 | 6667 | fdiaz | bandDataTypes[i] = this.getBandDescriptor(i).getDataType();
|
225 | bandNoData[i] = this.getNoData(rasterQuery, i);
|
||
226 | 6535 | fdiaz | try {
|
227 | pageManagers.add(getPageManagersInZoom(zoomLevel).get(i)); |
||
228 | } catch (ValidateDataParametersException | CreateEnvelopeException | DataException
|
||
229 | | CloneNotSupportedException e) {
|
||
230 | throw new BufferException(e); |
||
231 | } |
||
232 | } |
||
233 | 6532 | fdiaz | } |
234 | |||
235 | 6535 | fdiaz | Buffer buffer =
|
236 | bufferManager.createBuffer(getRows(zoomLevel), getColumns(zoomLevel), bandDataTypes, bandNoData, |
||
237 | projection, envelope, pageManagers); |
||
238 | 6532 | fdiaz | |
239 | 6535 | fdiaz | if(rasterQuery.getClip()!=null){ |
240 | Buffer completeBuffer = buffer;
|
||
241 | envelope = rasterQuery.getClip(); |
||
242 | 8842 | fdiaz | buffer = completeBuffer.clip(envelope); |
243 | 6535 | fdiaz | DisposeUtils.dispose(completeBuffer); |
244 | 6532 | fdiaz | } |
245 | |||
246 | 6535 | fdiaz | return buffer;
|
247 | 6532 | fdiaz | } catch (Exception e) { |
248 | throw new BufferException(e); |
||
249 | } |
||
250 | |||
251 | } |
||
252 | |||
253 | @Override
|
||
254 | 6667 | fdiaz | public BandDescriptorServices getBandDescriptor(int band) { |
255 | BandDescriptorServices descriptor = super.getBandDescriptor(band);
|
||
256 | switch (band) {
|
||
257 | case 0: |
||
258 | descriptor.setName("RED");
|
||
259 | descriptor.setDescription("RED");
|
||
260 | descriptor.setDataType(BufferManager.TYPE_BYTE); |
||
261 | case 1: |
||
262 | descriptor.setName("GREEN");
|
||
263 | descriptor.setDescription("GREEN");
|
||
264 | descriptor.setDataType(BufferManager.TYPE_BYTE); |
||
265 | case 2: |
||
266 | descriptor.setName("BLUE");
|
||
267 | descriptor.setDescription("BLUE");
|
||
268 | descriptor.setDataType(BufferManager.TYPE_BYTE); |
||
269 | case 3: |
||
270 | descriptor.setName("ALPHA");
|
||
271 | descriptor.setDescription("ALPHA");
|
||
272 | descriptor.setDataType(BufferManager.TYPE_BYTE); |
||
273 | } |
||
274 | return descriptor;
|
||
275 | 6532 | fdiaz | |
276 | } |
||
277 | |||
278 | 6667 | fdiaz | |
279 | 6532 | fdiaz | @Override
|
280 | public int getBands() { |
||
281 | return 4; |
||
282 | } |
||
283 | |||
284 | @Override
|
||
285 | public DataServerExplorer getExplorer() throws ReadException, ValidateDataParametersException { |
||
286 | DataManager manager = DALLocator.getDataManager(); |
||
287 | WMTSRasterServerExplorerParameters params; |
||
288 | try {
|
||
289 | params = |
||
290 | (WMTSRasterServerExplorerParameters) manager |
||
291 | .createServerExplorerParameters(WMTSRasterServerExplorer.NAME); |
||
292 | params.setService(((WMTSRasterProviderParameters) getParameters()).getService()); |
||
293 | // params.setXYAxisOrder(((WMTSRasterProviderParameters) getParameters()).getXYAxisOrder());
|
||
294 | return manager.openServerExplorer(WMTSRasterServerExplorer.NAME, (DataServerExplorerParameters) params);
|
||
295 | } catch (Exception e) { |
||
296 | throw new ReadException(this.getName(), e); |
||
297 | } |
||
298 | } |
||
299 | |||
300 | @Override
|
||
301 | public void open() throws OpenException { |
||
302 | 6667 | fdiaz | for(int i=0; i<getBands(); i++){ |
303 | this.getBandDescriptor(i).setDataType(DataTypes.BYTE);
|
||
304 | } |
||
305 | 6532 | fdiaz | } |
306 | |||
307 | @Override
|
||
308 | public ResourceProvider getResource() {
|
||
309 | return null; |
||
310 | } |
||
311 | |||
312 | @Override
|
||
313 | public Object getSourceId() { |
||
314 | return getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_SERVICE_PARAMETER_NAME);
|
||
315 | } |
||
316 | |||
317 | @Override
|
||
318 | public String getProviderName() { |
||
319 | return NAME;
|
||
320 | } |
||
321 | |||
322 | @Override
|
||
323 | public String getName() { //lista de capas |
||
324 | @SuppressWarnings("unchecked") |
||
325 | 6533 | fdiaz | String layerName = (String) getParameters().getDynValue("layer"); |
326 | return layerName;
|
||
327 | 6532 | fdiaz | } |
328 | |||
329 | @Override
|
||
330 | public String getFullName() { // host:port - lista de capas |
||
331 | |||
332 | StringBuilder builder = new StringBuilder(); |
||
333 | URL service = (URL)this.getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_SERVICE_PARAMETER_NAME); |
||
334 | builder.append(service.getHost()); |
||
335 | int port = service.getPort();
|
||
336 | if(port < 0){ |
||
337 | int defaultPort = service.getDefaultPort();
|
||
338 | if(defaultPort>=0){ |
||
339 | builder.append(":");
|
||
340 | builder.append(service.getDefaultPort()); |
||
341 | } |
||
342 | } else {
|
||
343 | builder.append(":");
|
||
344 | builder.append(port); |
||
345 | } |
||
346 | builder.append(" - ");
|
||
347 | builder.append(getName()); |
||
348 | return builder.toString();
|
||
349 | } |
||
350 | |||
351 | @Override
|
||
352 | public Object getDynValue(String name) throws DynFieldNotFoundException { |
||
353 | if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
|
||
354 | return this.getParameters().getDynValue(name); |
||
355 | } |
||
356 | if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
|
||
357 | 6535 | fdiaz | try {
|
358 | return this.getEnvelope(); |
||
359 | } catch (InitializeException e) {
|
||
360 | throw new DynFieldNotFoundException(name, this.getClass().getName()); |
||
361 | } |
||
362 | 6532 | fdiaz | } |
363 | return super.getDynValue(name); |
||
364 | } |
||
365 | |||
366 | 6535 | fdiaz | private Envelope getEnvelope() throws InitializeException { |
367 | if(this.envelope == null){ |
||
368 | GeometryManager geomManager = GeometryLocator.getGeometryManager(); |
||
369 | try {
|
||
370 | WMTSLayer wmtsLayer = getWMTSClient().getLayer(getLayerName()); |
||
371 | Rectangle2D rectangle2d = wmtsLayer.getWGS84BBox().toRectangle2D();
|
||
372 | Envelope envelopeWGS84 = geomManager.createEnvelope(rectangle2d.getMinX(), rectangle2d.getMinY(), rectangle2d.getMaxX(), rectangle2d.getMaxY(), Geometry.SUBTYPES.GEOM2D); |
||
373 | ICoordTrans ct = CRSFactory.getCRS("EPSG:4326").getCT(getProjection());
|
||
374 | this.envelope = envelopeWGS84.convert(ct);
|
||
375 | } catch (CreateEnvelopeException e) {
|
||
376 | throw new InitializeException("Can't create envelope.", e); |
||
377 | } |
||
378 | } |
||
379 | 6532 | fdiaz | return this.envelope; |
380 | } |
||
381 | |||
382 | @Override
|
||
383 | public TileStruct getTileStruct() {
|
||
384 | if (tileStruct == null) { |
||
385 | 6535 | fdiaz | /*
|
386 | 6533 | fdiaz | StringBuilder builder = new StringBuilder();
|
387 | builder.append("\n");
|
||
388 | builder.append("****************** LAYER ************************");
|
||
389 | builder.append("\n");
|
||
390 | builder.append("projection = ");
|
||
391 | builder.append(projection.getAbrev());
|
||
392 | builder.append("\n");
|
||
393 | WMTSLayer layer = wmtsClient.getLayer(wmtsStatus.getLayer());
|
||
394 | String layerAbstract = layer.getAbstract();
|
||
395 | builder.append("layerAbstract = ");
|
||
396 | builder.append(layerAbstract);
|
||
397 | builder.append("\n");
|
||
398 | String layerIdentifier = layer.getIdentifier();
|
||
399 | builder.append("layerIdentifier = ");
|
||
400 | builder.append(layerIdentifier);
|
||
401 | builder.append("\n");
|
||
402 | String layerTitle = layer.getTitle();
|
||
403 | builder.append("layerTitle = ");
|
||
404 | builder.append(layerTitle);
|
||
405 | builder.append("\n");
|
||
406 | WMTSBoundingBox layerBbox = layer.getBBox();
|
||
407 | builder.append("layerBbox = ");
|
||
408 | if (layerBbox != null) {
|
||
409 | builder.append(layerBbox.getLowerCorner()[0]);
|
||
410 | builder.append(", ");
|
||
411 | builder.append(layerBbox.getLowerCorner()[1]);
|
||
412 | builder.append(" - ");
|
||
413 | builder.append(layerBbox.getUpperCorner()[0]);
|
||
414 | builder.append(", ");
|
||
415 | builder.append(layerBbox.getUpperCorner()[1]);
|
||
416 | } else {
|
||
417 | builder.append("null");
|
||
418 | }
|
||
419 | builder.append("\n");
|
||
420 | |||
421 | WMTSBoundingBox layerWGS84BBox = layer.getWGS84BBox();
|
||
422 | builder.append("layerWGS84BBox = ");
|
||
423 | if (layerWGS84BBox != null) {
|
||
424 | builder.append(layerWGS84BBox.getLowerCorner()[0]);
|
||
425 | builder.append(", ");
|
||
426 | builder.append(layerWGS84BBox.getLowerCorner()[1]);
|
||
427 | builder.append(" - ");
|
||
428 | builder.append(layerWGS84BBox.getUpperCorner()[0]);
|
||
429 | builder.append(", ");
|
||
430 | builder.append(layerWGS84BBox.getUpperCorner()[1]);
|
||
431 | } else {
|
||
432 | builder.append("null");
|
||
433 | }
|
||
434 | builder.append("\n");
|
||
435 | Rectangle2D layerWGS84BBoxProjected = layer.getWGS84BBoxTransformed(projection.getAbrev());
|
||
436 | builder.append("layerWGS84BBoxProjected = ");
|
||
437 | if (layerWGS84BBoxProjected != null) {
|
||
438 | builder.append(layerWGS84BBoxProjected.getMinX());
|
||
439 | builder.append(", ");
|
||
440 | builder.append(layerWGS84BBoxProjected.getMinY());
|
||
441 | builder.append(" - ");
|
||
442 | builder.append(layerWGS84BBoxProjected.getMaxX());
|
||
443 | builder.append(", ");
|
||
444 | builder.append(layerWGS84BBoxProjected.getMaxY());
|
||
445 | } else {
|
||
446 | builder.append("null");
|
||
447 | }
|
||
448 | builder.append("\n");
|
||
449 | |||
450 | 6535 | fdiaz | List<WMTSTileMatrixSet> matrixSetsList = wmtsClient.getTileMatrixSet();
|
451 | 6533 | fdiaz | builder.append("\n");
|
452 | builder.append("############ TILE MATRIX SET ITERATOR ###########");
|
||
453 | builder.append("\n");
|
||
454 | 6535 | fdiaz | for (Iterator iterator = matrixSetsList.iterator(); iterator.hasNext();) {
|
455 | 6533 | fdiaz | builder.append("================ MATRIX SET =====================");
|
456 | builder.append("\n");
|
||
457 | WMTSTileMatrixSet wmtsTileMatrixSet = (WMTSTileMatrixSet) iterator.next();
|
||
458 | String identifier = wmtsTileMatrixSet.getIdentifier();
|
||
459 | builder.append("wmtsTileMatrixSet.getIdentifier() = ");
|
||
460 | builder.append(identifier);
|
||
461 | builder.append("\n");
|
||
462 | int layerInitialLevel = layer.getInitialLevel(identifier);
|
||
463 | builder.append("*** layerInitialLevel = ");
|
||
464 | builder.append(layerInitialLevel);
|
||
465 | builder.append("\n");
|
||
466 | String wellKnownScaleSet = wmtsTileMatrixSet.getWellKnownScaleSet();
|
||
467 | builder.append("wmtsTileMatrixSet.getWellKnownScaleSet() = ");
|
||
468 | builder.append(wellKnownScaleSet);
|
||
469 | builder.append("\n");
|
||
470 | WMTSBoundingBox bounding = wmtsTileMatrixSet.getBoundingBox();
|
||
471 | builder.append("wmtsTileMatrixSet.getBoundingBox() = ");
|
||
472 | builder.append(bounding.getLowerCorner()[0]);
|
||
473 | builder.append(", ");
|
||
474 | builder.append(bounding.getLowerCorner()[1]);
|
||
475 | builder.append(" - ");
|
||
476 | builder.append(bounding.getUpperCorner()[0]);
|
||
477 | builder.append(", ");
|
||
478 | builder.append(bounding.getUpperCorner()[1]);
|
||
479 | builder.append("\n");
|
||
480 | String supportedCRS = wmtsTileMatrixSet.getSupportedCRS();
|
||
481 | builder.append("wmtsTileMatrixSet.getSupportedCRS() = ");
|
||
482 | builder.append(supportedCRS);
|
||
483 | builder.append("\n");
|
||
484 | List<WMTSTileMatrix> tileMatrix = wmtsTileMatrixSet.getTileMatrix();
|
||
485 | builder.append("???????????????? TILE MATRIX ????????????????????");
|
||
486 | builder.append("\n");
|
||
487 | for (Iterator iterator2 = tileMatrix.iterator(); iterator2.hasNext();) {
|
||
488 | WMTSTileMatrix wmtsTileMatrix = (WMTSTileMatrix) iterator2.next();
|
||
489 | String ident = wmtsTileMatrix.getIdentifier(); // 0 ?tal vez el zoom level? parece que s?
|
||
490 | builder.append("ident = ");
|
||
491 | builder.append(ident);
|
||
492 | builder.append("\n");
|
||
493 | Rectangle2D bboxTileMatrixSet = wmtsTileMatrix.getBBoxTileMatrixSet(); // null
|
||
494 | builder.append("bboxTileMatrixSet = ");
|
||
495 | if (bboxTileMatrixSet != null) {
|
||
496 | builder.append(bboxTileMatrixSet.getMinX());
|
||
497 | builder.append(", ");
|
||
498 | builder.append(bboxTileMatrixSet.getMinY());
|
||
499 | builder.append(" - ");
|
||
500 | builder.append(bboxTileMatrixSet.getMaxX());
|
||
501 | builder.append(", ");
|
||
502 | builder.append(bboxTileMatrixSet.getMaxY());
|
||
503 | } else {
|
||
504 | builder.append("null");
|
||
505 | }
|
||
506 | builder.append("\n");
|
||
507 | double heightWCTile = wmtsTileMatrix.getHeightWCTile(false);
|
||
508 | builder.append("heightWCTile = ");
|
||
509 | builder.append(heightWCTile);
|
||
510 | builder.append("\n");
|
||
511 | double widthWCTile = wmtsTileMatrix.getWidthWCTile(false);
|
||
512 | builder.append("widthWCTile = ");
|
||
513 | builder.append(widthWCTile);
|
||
514 | builder.append("\n");
|
||
515 | double heightWCProjected = wmtsTileMatrix.getHeightWCTile(true);
|
||
516 | builder.append("heightWCTileProjected [CHUNGO] = ");
|
||
517 | builder.append(heightWCProjected);
|
||
518 | builder.append("\n");
|
||
519 | double widthWCProjected = wmtsTileMatrix.getWidthWCTile(true);
|
||
520 | builder.append("widthWCTileProjected [CHUNGO] = ");
|
||
521 | builder.append(widthWCProjected);
|
||
522 | builder.append("\n");
|
||
523 | long matrixHeight = wmtsTileMatrix.getMatrixHeight();
|
||
524 | builder.append("matrixHeight = ");
|
||
525 | builder.append(matrixHeight);
|
||
526 | builder.append("\n");
|
||
527 | long matrixWidth = wmtsTileMatrix.getMatrixWidth();
|
||
528 | builder.append("matrixWidth = ");
|
||
529 | builder.append(matrixWidth);
|
||
530 | builder.append("\n");
|
||
531 | double scaleDenominator = wmtsTileMatrix.getScaleDenominator(); // 2.79541132014358E8
|
||
532 | // puede ser el pixelSize
|
||
533 | builder.append("scaleDenominator = ");
|
||
534 | builder.append(scaleDenominator);
|
||
535 | builder.append("\n");
|
||
536 | int tileHeight = wmtsTileMatrix.getTileHeight(); // ??? rows in tile
|
||
537 | builder.append("tileHeight = ");
|
||
538 | builder.append(tileHeight);
|
||
539 | builder.append("\n");
|
||
540 | int tileWidth = wmtsTileMatrix.getTileWidth(); // ??? columns in tile
|
||
541 | builder.append("tileWidth = ");
|
||
542 | builder.append(tileWidth);
|
||
543 | builder.append("\n");
|
||
544 | double[] topLeftCorner = wmtsTileMatrix.getTopLeftCorner();
|
||
545 | builder.append("topLeftCorner = ");
|
||
546 | builder.append(topLeftCorner[0]);
|
||
547 | builder.append(", ");
|
||
548 | builder.append(topLeftCorner[1]);
|
||
549 | builder.append("\n");
|
||
550 | |||
551 | builder.append("-------------------------------------------------");
|
||
552 | builder.append("\n");
|
||
553 | |||
554 | }
|
||
555 | builder.append("=================================================");
|
||
556 | builder.append("\n");
|
||
557 | }
|
||
558 | builder.append("#################################################");
|
||
559 | builder.append("\n");
|
||
560 | |||
561 | logger.info(builder.toString());
|
||
562 | 6535 | fdiaz | */
|
563 | 6533 | fdiaz | |
564 | 6535 | fdiaz | autoOpen(); |
565 | 6532 | fdiaz | try {
|
566 | 6535 | fdiaz | this.tileStruct = new DefaultTileStruct(); |
567 | this.columnsPerTile = DEFAULT_BUFFER_SIZE;
|
||
568 | this.rowsPerTile = DEFAULT_BUFFER_SIZE;
|
||
569 | this.tileStruct.setEnvelope(getEnvelope());
|
||
570 | tileMatrixPerZoomLevel = new HashMap<Integer, WMTSTileMatrix>(); |
||
571 | 6532 | fdiaz | |
572 | 6535 | fdiaz | WMTSTileMatrixSet matrixSet = getTileMatrixSet(); |
573 | |||
574 | HashMap<Integer, Integer> tileWidthsCounter = new HashMap<Integer, Integer>(); |
||
575 | HashMap<Integer, Integer> tileHeightsCounter = new HashMap<Integer, Integer>(); |
||
576 | 6532 | fdiaz | Map<Integer, Double> zoomLevels = new HashMap<Integer, Double>(); |
577 | 6535 | fdiaz | int zoomLevel = 0; |
578 | if(matrixSet!=null){ |
||
579 | List<WMTSTileMatrix> tileMatrixList = matrixSet.getTileMatrix();
|
||
580 | for (Iterator iterator = tileMatrixList.iterator(); iterator.hasNext();) { |
||
581 | WMTSTileMatrix wmtsTileMatrix = (WMTSTileMatrix) iterator.next(); |
||
582 | long levelColumns = wmtsTileMatrix.getMatrixWidth()*wmtsTileMatrix.getTileWidth();
|
||
583 | 6540 | fdiaz | |
584 | 6535 | fdiaz | double levelWidth = wmtsTileMatrix.getMatrixWidth()*wmtsTileMatrix.getWidthWCTile(getProjection().isProjected());
|
585 | double pixelSize = levelWidth/levelColumns;
|
||
586 | zoomLevels.put(zoomLevel, pixelSize); |
||
587 | tileMatrixPerZoomLevel.put(zoomLevel, wmtsTileMatrix); |
||
588 | // Aprovechamos el bucle para contar los distintos
|
||
589 | // valores que el servidor tiene para el tama?o de los
|
||
590 | // tiles en cada nivel de zoom
|
||
591 | int tileWidth = wmtsTileMatrix.getTileWidth();
|
||
592 | if(!tileWidthsCounter.containsKey(tileWidth)){
|
||
593 | tileWidthsCounter.put(tileWidth, 1);
|
||
594 | } else {
|
||
595 | tileWidthsCounter.put(tileWidth, tileWidthsCounter.get(tileWidth)+1);
|
||
596 | } |
||
597 | int tileHeight = wmtsTileMatrix.getTileHeight();
|
||
598 | if(!tileHeightsCounter.containsKey(tileHeight)){
|
||
599 | tileHeightsCounter.put(tileHeight, 1);
|
||
600 | } else {
|
||
601 | tileHeightsCounter.put(tileHeight, tileHeightsCounter.get(tileHeight)+1);
|
||
602 | } |
||
603 | 8700 | fdiaz | maxZoomLevel = zoomLevel; |
604 | 6535 | fdiaz | zoomLevel++; |
605 | } |
||
606 | 6532 | fdiaz | } |
607 | 6535 | fdiaz | //seleccionamos los m?s usados
|
608 | Integer aux = tileWidthsCounter.get(columnsPerTile);
|
||
609 | if(aux==null){ |
||
610 | aux = 0;
|
||
611 | 6532 | fdiaz | } |
612 | 6535 | fdiaz | Iterator<Entry<Integer, Integer>> it = tileWidthsCounter.entrySet().iterator(); |
613 | while (it.hasNext()) {
|
||
614 | Entry<Integer, Integer> entry = it.next(); |
||
615 | if(entry.getValue()>=aux){
|
||
616 | aux = entry.getValue(); |
||
617 | columnsPerTile = entry.getKey(); |
||
618 | } |
||
619 | } |
||
620 | aux = tileHeightsCounter.get(rowsPerTile); |
||
621 | if(aux==null){ |
||
622 | aux = 0;
|
||
623 | } |
||
624 | Iterator<Entry<Integer, Integer>> it2 = tileWidthsCounter.entrySet().iterator(); |
||
625 | while (it2.hasNext()) {
|
||
626 | Entry<Integer, Integer> entry = it2.next(); |
||
627 | if(entry.getValue()>=aux){
|
||
628 | aux = entry.getValue(); |
||
629 | rowsPerTile = entry.getKey(); |
||
630 | } |
||
631 | } |
||
632 | 6532 | fdiaz | |
633 | 6535 | fdiaz | //y los asignamos
|
634 | this.tileStruct.setColumnsPerTile(columnsPerTile);
|
||
635 | this.tileStruct.setRowsPerTile(rowsPerTile);
|
||
636 | |||
637 | //
|
||
638 | this.tileStruct.setPixelSizePerZoomLevel(zoomLevels);
|
||
639 | } catch (LocatorException | InitializeException e) {
|
||
640 | 6532 | fdiaz | logger.warn("Can't create world extent of GoogleMaps", e);
|
641 | } |
||
642 | } |
||
643 | 6535 | fdiaz | return this.tileStruct; |
644 | 6532 | fdiaz | } |
645 | |||
646 | 6535 | fdiaz | /**
|
647 | * @return
|
||
648 | * @throws InitializeException
|
||
649 | */
|
||
650 | private WMTSTileMatrixSet getTileMatrixSet() throws InitializeException { |
||
651 | WMTSTileMatrixSet matrixSet = null;
|
||
652 | List<WMTSTileMatrixSet> matrixSets = wmtsClient.getTileMatrixSet();
|
||
653 | for (Iterator<WMTSTileMatrixSet> iterator = matrixSets.iterator(); iterator.hasNext();) { |
||
654 | WMTSTileMatrixSet wmtsTileMatrixSet = (WMTSTileMatrixSet) iterator.next(); |
||
655 | String supportedCrs = wmtsTileMatrixSet.getSupportedCRS();
|
||
656 | IProjection supportedProjection = null;
|
||
657 | try {
|
||
658 | supportedProjection = CRSFactory.getCRS(supportedCrs); |
||
659 | if(supportedProjection==null){ |
||
660 | continue;
|
||
661 | } |
||
662 | |||
663 | } catch (Exception e) { |
||
664 | continue;
|
||
665 | } |
||
666 | if ( supportedProjection.equals(getProjection()) ){
|
||
667 | matrixSet = wmtsTileMatrixSet; |
||
668 | break;
|
||
669 | } |
||
670 | } |
||
671 | return matrixSet;
|
||
672 | } |
||
673 | |||
674 | 6532 | fdiaz | private List<PageManager> getPageManagersInZoom(int zoomLevel) throws ValidateDataParametersException, CreateEnvelopeException, BufferException, DataException, CloneNotSupportedException { |
675 | List<PageManager> pageManagersInZoom = this.pageManagersPerZoomLevel.get(zoomLevel); |
||
676 | if (pageManagersInZoom == null) { |
||
677 | pageManagersInZoom = new ArrayList<PageManager>(); |
||
678 | for (int i = 0; i < getBands(); i++) { |
||
679 | 6535 | fdiaz | //FIXME el getTileStruct no sirve para este bandTileManager
|
680 | 8842 | fdiaz | pageManagersInZoom.add(new WMTSBandTileManager(getTileStruct(), this.getWMTSImage(), zoomLevel, i)); |
681 | 6532 | fdiaz | } |
682 | this.pageManagersPerZoomLevel.put(zoomLevel, pageManagersInZoom);
|
||
683 | } |
||
684 | return pageManagersInZoom;
|
||
685 | } |
||
686 | |||
687 | /**
|
||
688 | * @param zoomLevel
|
||
689 | * @return rows per zoom level
|
||
690 | */
|
||
691 | public int getRows(int zoomLevel) { |
||
692 | return (int) (Math.round(getTileStruct().getEnvelope().getLength(DIMENSIONS.Y) / this.getTileStruct().getPixelSizePerZoomLevel().get(zoomLevel))); |
||
693 | } |
||
694 | |||
695 | /**
|
||
696 | * @param zoomLevel
|
||
697 | * @return columns per zoom level
|
||
698 | */
|
||
699 | public int getColumns(int zoomLevel) { |
||
700 | return (int) (Math.round(getTileStruct().getEnvelope().getLength(DIMENSIONS.X) / this.getTileStruct().getPixelSizePerZoomLevel().get(zoomLevel))); |
||
701 | } |
||
702 | |||
703 | /**
|
||
704 | * @param pixelSize
|
||
705 | * @return The appropriate zoom level for the pizelSize
|
||
706 | */
|
||
707 | private int getZoomLvlForPixelSize(double pixelSize) { |
||
708 | 8700 | fdiaz | //FIXME: Elegir el c?digo id?neo
|
709 | // Este trozo de c?digo selecciona un zoom superior con lo que,
|
||
710 | // al hacer la interpolaci?n se generar?n p?xeles m?s gordos
|
||
711 | 6532 | fdiaz | int zoom = 0; |
712 | 8700 | fdiaz | Map<Integer, Double> pixelSizePerZoomLevel = tileStruct.getPixelSizePerZoomLevel(); |
713 | |||
714 | SortedSet<Integer> keySet = new TreeSet<>(Collections.reverseOrder()); |
||
715 | keySet.addAll(pixelSizePerZoomLevel.keySet()); |
||
716 | Iterator<Integer> iterator = keySet.iterator(); |
||
717 | while(iterator.hasNext()){
|
||
718 | zoom = iterator.next(); |
||
719 | double levelPixelSize = pixelSizePerZoomLevel.get(zoom);
|
||
720 | if (pixelSize <= levelPixelSize) {
|
||
721 | return zoom;
|
||
722 | } |
||
723 | } |
||
724 | |||
725 | return zoom;
|
||
726 | |||
727 | // Este trozo de c?digo selecciona un zoom inferior con lo que,
|
||
728 | // al hacer la interpolaci?n se perder?n p?xeles
|
||
729 | // repercutiendo en la legibilidad de las leyendas
|
||
730 | /*
|
||
731 | int zoom = 0;
|
||
732 | 6532 | fdiaz | Map<Integer, Double> pixelSizePerZoomLevel = getTileStruct().getPixelSizePerZoomLevel();
|
733 | for (int i : pixelSizePerZoomLevel.keySet()) {
|
||
734 | zoom = i;
|
||
735 | double levelPixelSize = pixelSizePerZoomLevel.get(zoom);
|
||
736 | if (pixelSize >= levelPixelSize) {
|
||
737 | return zoom;
|
||
738 | }
|
||
739 | }
|
||
740 | return zoom;
|
||
741 | 8700 | fdiaz | */
|
742 | 6532 | fdiaz | } |
743 | |||
744 | private WMTSImage getWMTSImage() {
|
||
745 | if(this.image == null){ |
||
746 | 6535 | fdiaz | this.image = new WMTSImage(getTileStruct(), this.tileMatrixPerZoomLevel, this); |
747 | 6532 | fdiaz | } |
748 | return this.image; |
||
749 | } |
||
750 | |||
751 | 6535 | fdiaz | protected IProjection getProjection(){
|
752 | if(this.projection==null){ |
||
753 | projection = (IProjection) (getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_CRS_PARAMETER_NAME)); |
||
754 | } |
||
755 | return this.projection; |
||
756 | } |
||
757 | 6532 | fdiaz | |
758 | 6535 | fdiaz | protected WMTSClient getWMTSClient() throws InitializeException { |
759 | if (wmtsClient == null) { |
||
760 | WMTSRasterProviderParameters parameters = (WMTSRasterProviderParameters) getParameters(); |
||
761 | URL service = parameters.getService();
|
||
762 | try {
|
||
763 | wmtsClient = WMTSOGCLocator.getManager().createWMTSClient(service.toString()); |
||
764 | 6541 | fdiaz | Boolean forceChangeAxisOrder = (Boolean) getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_FORCECHANGEAXISORDER_PARAMETER_NAME); |
765 | 6540 | fdiaz | if(forceChangeAxisOrder!=null){ |
766 | wmtsClient.setForceChangeAxisOrder(forceChangeAxisOrder.booleanValue()); |
||
767 | } else {
|
||
768 | wmtsClient.setForceChangeAxisOrder(false);
|
||
769 | } |
||
770 | 6535 | fdiaz | wmtsClient.connect(true, null); |
771 | } catch (IOException e) { |
||
772 | 8700 | fdiaz | throw new InitializeException("Can't create WMTSClient with from service '" + service.toString() + "'", |
773 | 6535 | fdiaz | e); |
774 | } |
||
775 | } |
||
776 | return wmtsClient;
|
||
777 | } |
||
778 | |||
779 | protected int getRowsPerTile() { |
||
780 | return this.rowsPerTile; |
||
781 | }; |
||
782 | |||
783 | protected int getColumnsPerTile() { |
||
784 | return this.columnsPerTile; |
||
785 | }; |
||
786 | |||
787 | 6551 | fdiaz | @Override
|
788 | public Image getImageLegend() { |
||
789 | File file;
|
||
790 | BufferedImage img = null; |
||
791 | try {
|
||
792 | WMTSLayer wmtsLayer = getWMTSClient().getLayer(getLayerName()); |
||
793 | WMTSStyle wmtsStyle = null;
|
||
794 | List<WMTSStyle> wmtsStyles = wmtsLayer.getStyle();
|
||
795 | 8842 | fdiaz | for (Iterator<WMTSStyle> iterator = wmtsStyles.iterator(); iterator.hasNext();) { |
796 | 6551 | fdiaz | wmtsStyle = (WMTSStyle) iterator.next(); |
797 | if (wmtsStyle.getIdentifier().equalsIgnoreCase(wmtsStatus.getStyle())) {
|
||
798 | break;
|
||
799 | } |
||
800 | wmtsStyle = null;
|
||
801 | } |
||
802 | 6535 | fdiaz | |
803 | 6551 | fdiaz | file = getWMTSClient().getLegendGraphic(wmtsLayer, wmtsStyle, null);
|
804 | img = ImageIO.read(file);
|
||
805 | } catch (InitializeException | WMTSException | IOException e) { |
||
806 | logger.warn("Can't read image legend of WMTS Provider", e);
|
||
807 | } |
||
808 | return img;
|
||
809 | } |
||
810 | |||
811 | 6682 | fdiaz | @Override
|
812 | public BufferDimensions getDimensions() throws InitializeException { |
||
813 | if(this.dimensions==null){; |
||
814 | 8700 | fdiaz | Double pixelSize = getTileStruct().getPixelSizePerZoomLevel().get(getMaxZoomLevel());
|
815 | 6682 | fdiaz | Envelope envelope = this.getEnvelope();
|
816 | int rows = (int)Math.round(envelope.getLength(DIMENSIONS.Y)/pixelSize); |
||
817 | int columns = (int)Math.round(envelope.getLength(DIMENSIONS.X)/pixelSize); |
||
818 | this.dimensions = BufferLocator.getBufferManager().createBufferDimensions(rows, columns, envelope);
|
||
819 | } |
||
820 | return this.dimensions; |
||
821 | } |
||
822 | |||
823 | 8700 | fdiaz | /**
|
824 | * @return the maxZoomLevel
|
||
825 | */
|
||
826 | public int getMaxZoomLevel() { |
||
827 | return maxZoomLevel;
|
||
828 | } |
||
829 | |||
830 | 8842 | fdiaz | @Override
|
831 | protected void doDispose() throws BaseException { |
||
832 | super.doDispose();
|
||
833 | DisposeUtils.dispose((Disposable) this.tileStruct);
|
||
834 | tileStruct = null;
|
||
835 | DisposeUtils.dispose(this.image);
|
||
836 | this.image = null; |
||
837 | 8700 | fdiaz | |
838 | 8842 | fdiaz | Set<Entry<Integer, List<PageManager>>> entries = this.pageManagersPerZoomLevel.entrySet(); |
839 | for (Iterator<Entry<Integer, List<PageManager>>> iterator = entries.iterator(); iterator.hasNext();) { |
||
840 | Entry<Integer, List<PageManager>> entry = (Entry<Integer, List<PageManager>>) iterator.next(); |
||
841 | List<PageManager> pageManagers = entry.getValue();
|
||
842 | for (Iterator iterator2 = pageManagers.iterator(); iterator2.hasNext();) { |
||
843 | PageManager pageManager = (PageManager) iterator2.next(); |
||
844 | DisposeUtils.dispose(pageManager); |
||
845 | iterator2.remove(); |
||
846 | } |
||
847 | iterator.remove(); |
||
848 | } |
||
849 | pageManagersPerZoomLevel = null;
|
||
850 | |||
851 | |||
852 | } |
||
853 | |||
854 | 6532 | fdiaz | } |