Statistics
| Revision:

gvsig-raster / org.gvsig.raster / branches / org.gvsig.raster.2.4 / org.gvsig.raster.googlemaps / org.gvsig.raster.googlemaps.provider / src / main / java / org / gvsig / raster / googlemaps / provider / GoogleMapsRasterProvider.java @ 8836

History | View | Annotate | Download (13.4 KB)

1
package org.gvsig.raster.googlemaps.provider;
2

    
3
import java.util.ArrayList;
4
import java.util.HashMap;
5
import java.util.Iterator;
6
import java.util.List;
7
import java.util.Map;
8
import java.util.Map.Entry;
9

    
10
import org.apache.commons.lang3.StringUtils;
11
import org.cresques.cts.IProjection;
12
import org.slf4j.Logger;
13
import org.slf4j.LoggerFactory;
14

    
15
import org.gvsig.fmap.crs.CRSFactory;
16
import org.gvsig.fmap.dal.DataServerExplorer;
17
import org.gvsig.fmap.dal.DataStore;
18
import org.gvsig.fmap.dal.DataStoreParameters;
19
import org.gvsig.fmap.dal.FileHelper;
20
import org.gvsig.fmap.dal.exception.DataException;
21
import org.gvsig.fmap.dal.exception.InitializeException;
22
import org.gvsig.fmap.dal.exception.OpenException;
23
import org.gvsig.fmap.dal.exception.ReadException;
24
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
25
import org.gvsig.fmap.dal.raster.api.BandQuery;
26
import org.gvsig.fmap.dal.raster.api.RasterQuery;
27
import org.gvsig.fmap.dal.raster.spi.AbstractRasterStoreProvider;
28
import org.gvsig.fmap.dal.raster.spi.BandDescriptorServices;
29
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
30
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
31
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
32
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
33
import org.gvsig.fmap.geom.GeometryLocator;
34
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
35
import org.gvsig.fmap.geom.primitive.Envelope;
36
import org.gvsig.googlemaps.lib.api.MapTypes;
37
import org.gvsig.metadata.MetadataLocator;
38
import org.gvsig.metadata.MetadataManager;
39
import org.gvsig.metadata.exceptions.MetadataException;
40
import org.gvsig.raster.lib.buffer.api.Buffer;
41
import org.gvsig.raster.lib.buffer.api.BufferDimensions;
42
import org.gvsig.raster.lib.buffer.api.BufferLocator;
43
import org.gvsig.raster.lib.buffer.api.BufferManager;
44
import org.gvsig.raster.lib.buffer.api.NoData;
45
import org.gvsig.raster.lib.buffer.api.PageManager;
46
import org.gvsig.raster.lib.buffer.api.TileStruct;
47
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
48
import org.gvsig.raster.lib.buffer.spi.DefaultTileStruct;
49
import org.gvsig.tools.ToolsLocator;
50
import org.gvsig.tools.dataTypes.DataTypes;
51
import org.gvsig.tools.dispose.Disposable;
52
import org.gvsig.tools.dispose.DisposeUtils;
53
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
54
import org.gvsig.tools.exception.BaseException;
55
import org.gvsig.tools.i18n.I18nManager;
56
import org.gvsig.tools.locator.LocatorException;
57

    
58

    
59
/**
60
 * @author fdiaz
61
 *
62
 */
63
public class GoogleMapsRasterProvider extends AbstractRasterStoreProvider {
64

    
65
    private static final Logger logger =
66
        LoggerFactory.getLogger(GoogleMapsRasterProvider.class);
67

    
68
    public static String NAME = "GoogleMaps";
69
    public static String DESCRIPTION = "Google Maps";
70
    public static final String METADATA_DEFINITION_NAME = "GoogleMaps";
71
    static IProjection GOOGLE_MAPS_PROJECTION = CRSFactory.getCRS("EPSG:3857");
72

    
73

    
74
    private GoogleMapsImage image;
75
    TileStruct tileStruct = null;
76
    Map<Integer,List<PageManager>> pageManagersPerZoomLevel = null;
77

    
78
    private Envelope worldExtent;
79

    
80
    protected static void registerMetadataDefinition() throws MetadataException {
81
        MetadataManager manager = MetadataLocator.getMetadataManager();
82
        if (manager.getDefinition(METADATA_DEFINITION_NAME) == null) {
83
            manager.addDefinition(METADATA_DEFINITION_NAME,
84
                GoogleMapsRasterProviderParameters.class.getResourceAsStream("GoogleMapsRasterMetadata.xml"),
85
                GoogleMapsRasterProviderParameters.class.getClassLoader());
86
        }
87
    }
88

    
89

    
90
    protected GoogleMapsRasterProvider(DataStoreParameters params, DataStoreProviderServices storeServices) {
91
        super(params, storeServices, FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME));
92
        pageManagersPerZoomLevel = new HashMap<Integer, List<PageManager>>();
93
    }
94

    
95
    @Override
96
    public Buffer createBuffer(RasterQuery rasterQuery) throws BufferException {
97

    
98
        BufferManager bufferManager = BufferLocator.getBufferManager();
99
        int[] bandDataTypes;
100
        List<PageManager> pageManagers = new ArrayList<PageManager>();
101
        NoData[] bandNoData;
102
        Envelope envelope = getTileStruct().getEnvelope();
103
        double pixelSize = rasterQuery.getPixelSize();
104
        int zoomLevel;
105
        if(pixelSize == 0){
106
            zoomLevel = 0;
107
        } else {
108
            zoomLevel = getZoomLvlForPixelSize(pixelSize);
109
        }
110

    
111
            if (!rasterQuery.getBands().isEmpty()) {
112
                List<BandQuery> bands;
113
                bands = rasterQuery.getBands();
114
                bandDataTypes = new int[bands.size()];
115
                bandNoData = new NoData[bands.size()];
116

    
117
                for (BandQuery bandQuery : bands) {
118
                    int band = bandQuery.getBand();
119
                    bandDataTypes[band] = this.getBandDescriptor(band).getDataType();
120
                    bandNoData[band] = this.getNoData(rasterQuery, band);
121
                    try {
122
                        pageManagers.add(getPageManagersInZoom(zoomLevel).get(band));
123
                    } catch (ValidateDataParametersException | CreateEnvelopeException | DataException
124
                        | CloneNotSupportedException e) {
125
                        // TODO Auto-generated catch block
126
                        throw new BufferException(e);
127
                    }
128
                }
129
            } else {
130
                int bands = getBands();
131
                bandDataTypes = new int[bands];
132
                bandNoData = new NoData[bands];
133
                for (int i = 0; i < bands; i++) {
134
                    bandDataTypes[i] = this.getBandDescriptor(i).getDataType();
135
                    bandNoData[i] = this.getNoData(rasterQuery, i);
136
                    try {
137
                        pageManagers.add(getPageManagersInZoom(zoomLevel).get(i));
138
                    } catch (ValidateDataParametersException | CreateEnvelopeException | DataException
139
                        | CloneNotSupportedException e) {
140
                        throw new BufferException(e);
141
                    }
142
                }
143
            }
144

    
145
        Buffer buffer =
146
            bufferManager.createBuffer(getRows(zoomLevel), getColumns(zoomLevel), bandDataTypes, bandNoData,
147
                GOOGLE_MAPS_PROJECTION, envelope, pageManagers);
148

    
149
        if(rasterQuery.getClip()!=null){
150
            Buffer completeBuffer = buffer;
151
            envelope  = rasterQuery.getClip();
152
            buffer = completeBuffer.clip(envelope);
153
            DisposeUtils.dispose(completeBuffer);
154
        }
155

    
156
        return buffer;
157
    }
158

    
159
    @Override
160
    public BandDescriptorServices getBandDescriptor(int band) {
161
        BandDescriptorServices descriptor = super.getBandDescriptor(band);
162
      switch (band) {
163
      case 0:
164
          descriptor.setName("RED");
165
          descriptor.setDescription("RED");
166
          descriptor.setDataType(BufferManager.TYPE_BYTE);
167
      case 1:
168
          descriptor.setName("GREEN");
169
          descriptor.setDescription("GREEN");
170
          descriptor.setDataType(BufferManager.TYPE_BYTE);
171
      case 2:
172
          descriptor.setName("BLUE");
173
          descriptor.setDescription("BLUE");
174
          descriptor.setDataType(BufferManager.TYPE_BYTE);
175
      case 3:
176
          descriptor.setName("ALPHA");
177
          descriptor.setDescription("ALPHA");
178
          descriptor.setDataType(BufferManager.TYPE_BYTE);
179
      }
180
      return descriptor;
181

    
182
    }
183

    
184
    @Override
185
    public int getBands() {
186
        return 4;
187
    }
188

    
189
    @Override
190
    public DataServerExplorer getExplorer() throws ReadException, ValidateDataParametersException {
191
        // TODO Auto-generated method stub
192
        return null;
193
    }
194

    
195
    @Override
196
    public void open() throws OpenException {
197
        for(int i=0; i<getBands(); i++){
198
            this.getBandDescriptor(i).setDataType(DataTypes.BYTE);
199
        }
200
    }
201

    
202
    @Override
203
    public ResourceProvider getResource() {
204
        return null;
205
    }
206

    
207
    @Override
208
    public Object getSourceId() {
209
        return NAME+"-"+getParameters().getDynValue("mapType");
210
    }
211

    
212
    @Override
213
    public String getProviderName() {
214
        return NAME;
215
    }
216

    
217
    @Override
218
    public String getName() {
219
        I18nManager i18nManager = ToolsLocator.getI18nManager();
220
        String mapId = (String) getParameters().getDynValue("mapType");
221
        MapTypes mapType = MapTypes.valueOf(StringUtils.upperCase(mapId));
222

    
223
        return i18nManager.getTranslation("_google_maps")+" "+mapType.toString();
224
    }
225

    
226
    @Override
227
    public String getFullName() {
228
        return NAME+"-"+getParameters().getDynValue("mapType");
229
    }
230

    
231
    public TileStruct getTileStruct() {
232
        if(tileStruct == null){
233
            autoOpen();
234
            tileStruct = new DefaultTileStruct();
235
            tileStruct.setColumnsPerTile(GoogleMapsRasterLibrary.TILE_SIZE);
236
            tileStruct.setRowsPerTile(GoogleMapsRasterLibrary.TILE_SIZE);
237

    
238
            //FIXME: ??
239
//            tileStruct.setProviderName("GTIFF");
240

    
241
            try {
242
                worldExtent = GeometryLocator.getGeometryManager().createEnvelope(-20037508, -20037508, 20037508, 20037508, SUBTYPES.GEOM2D);
243
                tileStruct.setEnvelope(worldExtent);
244

    
245
                Map<Integer, Double> zoomLevels = new HashMap<Integer, Double>();
246

    
247
                double pixelSize = worldExtent.getLength(DIMENSIONS.X)/GoogleMapsRasterLibrary.GOOGLE_MAPS_TILE_SIZE;
248
                for (int zoomLevel = 0; zoomLevel <= GoogleMapsRasterLibrary.MAX_ZOOM_LEVEL; zoomLevel++) {
249
                    zoomLevels.put(zoomLevel, pixelSize);
250
                    pixelSize = pixelSize/2;
251
                }
252

    
253
                tileStruct.setPixelSizePerZoomLevel(zoomLevels);
254
            } catch (LocatorException | CreateEnvelopeException e) {
255
                logger.warn("Can't create world extent of GoogleMaps", e);
256
            }
257
        }
258
        return this.tileStruct;
259
    }
260

    
261
    private GoogleMapsImage getGoogleMapsImage() {
262
        if(this.image == null){
263
            this.image = new GoogleMapsImage(getTileStruct(), this);
264
        }
265
        return this.image;
266
    }
267

    
268
    /**
269
     * @param pixelSize
270
     * @return The appropriate zoom level for the pizelSize
271
     */
272
    private int getZoomLvlForPixelSize(double pixelSize) {
273
        int zoom = 0;
274
        Map<Integer, Double> pixelSizePerZoomLevel = getTileStruct().getPixelSizePerZoomLevel();
275
        for (int i : pixelSizePerZoomLevel.keySet()) {
276
            zoom = i;
277
            double levelPixelSize = pixelSizePerZoomLevel.get(zoom);
278
            if (pixelSize >= levelPixelSize) {
279
                return zoom;
280
            }
281
        }
282
        return zoom;
283
    }
284

    
285
    private List<PageManager> getPageManagersInZoom(int zoomLevel) throws ValidateDataParametersException, CreateEnvelopeException, BufferException, DataException, CloneNotSupportedException {
286
        List<PageManager> pageManagersInZoom = this.pageManagersPerZoomLevel.get(zoomLevel);
287
        if (pageManagersInZoom == null) {
288
            pageManagersInZoom = new ArrayList<PageManager>();
289
            for (int i = 0; i < getBands(); i++) {
290
                pageManagersInZoom.add(new GoogleMapsBandTileManager(getTileStruct(), this.getGoogleMapsImage(), zoomLevel, i, this));
291
            }
292
            this.pageManagersPerZoomLevel.put(zoomLevel, pageManagersInZoom);
293
        }
294
        return pageManagersInZoom;
295
    }
296

    
297
    /**
298
     * @param zoomLevel
299
     * @return rows per zoom level
300
     */
301
    public int getRows(int zoomLevel) {
302
        return (int) (Math.round(getTileStruct().getEnvelope().getLength(DIMENSIONS.Y) / this.getTileStruct().getPixelSizePerZoomLevel().get(zoomLevel)));
303
    }
304

    
305
    /**
306
     * @param zoomLevel
307
     * @return columns per zoom level
308
     */
309
    public int getColumns(int zoomLevel) {
310
        return (int) (Math.round(getTileStruct().getEnvelope().getLength(DIMENSIONS.X) / this.getTileStruct().getPixelSizePerZoomLevel().get(zoomLevel)));
311
    }
312

    
313
    @Override
314
    public Object getDynValue(String name) throws DynFieldNotFoundException {
315
        if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
316
            return this.getTileStruct().getEnvelope(); //.worldExtent;
317
        } else if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
318
            return GOOGLE_MAPS_PROJECTION;
319
        }
320
        return super.getDynValue(name);
321
    }
322

    
323
    @Override
324
    public BufferDimensions getDimensions() throws InitializeException {
325
        if(this.dimensions==null){;
326
            Double pixelSize = getTileStruct().getPixelSizePerZoomLevel().get(GoogleMapsRasterLibrary.MAX_ZOOM_LEVEL);
327
            Envelope envelope = getTileStruct().getEnvelope();
328
            int rows = (int)Math.round(envelope.getLength(DIMENSIONS.Y)/pixelSize);
329
            int columns = rows;
330
            this.dimensions = BufferLocator.getBufferManager().createBufferDimensions(rows, columns, envelope);
331
        }
332
        return this.dimensions;
333
    }
334

    
335
    @Override
336
    public void doDispose() throws BaseException {
337
        super.doDispose();
338

    
339
        for (Iterator<Entry<Integer, List<PageManager>>> iterator = pageManagersPerZoomLevel.entrySet().iterator(); iterator.hasNext();) {
340
            Entry<Integer, List<PageManager>> entry = iterator.next();
341
            List<PageManager> pageManagers = entry.getValue();
342
            for(Iterator<PageManager> it = pageManagers.iterator(); it.hasNext();){
343
                PageManager pageManager = it.next();
344
                DisposeUtils.dispose(pageManager);
345
                it.remove();
346
            }
347
            iterator.remove();
348
        }
349
        DisposeUtils.dispose((Disposable) tileStruct);
350
        DisposeUtils.dispose(image);
351
        tileStruct=null;
352
        image=null;
353
    }
354
}