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 @ 8804

History | View | Annotate | Download (12.5 KB)

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

    
3
import java.util.ArrayList;
4
import java.util.HashMap;
5
import java.util.List;
6
import java.util.Map;
7

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

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

    
54

    
55
/**
56
 * @author fdiaz
57
 *
58
 */
59
public class GoogleMapsRasterProvider extends AbstractRasterStoreProvider {
60

    
61
    private static final Logger logger =
62
        LoggerFactory.getLogger(GoogleMapsRasterProvider.class);
63

    
64
    public static String NAME = "GoogleMaps";
65
    public static String DESCRIPTION = "Google Maps";
66
    public static final String METADATA_DEFINITION_NAME = "GoogleMaps";
67
    static IProjection GOOGLE_MAPS_PROJECTION = CRSFactory.getCRS("EPSG:3857");
68

    
69

    
70
    private GoogleMapsImage image;
71
    TileStruct tileStruct = null;
72
    Map<Integer,List<PageManager>> pageManagersPerZoomLevel = null;
73

    
74
    private Envelope worldExtent;
75

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

    
85

    
86
    protected GoogleMapsRasterProvider(DataStoreParameters params, DataStoreProviderServices storeServices) {
87
        super(params, storeServices, FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME));
88
        pageManagersPerZoomLevel = new HashMap<Integer, List<PageManager>>();
89
    }
90

    
91
    @Override
92
    public Buffer createBuffer(RasterQuery rasterQuery) throws BufferException {
93

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

    
107
            if (!rasterQuery.getBands().isEmpty()) {
108
                List<BandQuery> bands;
109
                bands = rasterQuery.getBands();
110
                bandDataTypes = new int[bands.size()];
111
                bandNoData = new NoData[bands.size()];
112

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

    
141
        Buffer buffer =
142
            bufferManager.createBuffer(getRows(zoomLevel), getColumns(zoomLevel), bandDataTypes, bandNoData,
143
                GOOGLE_MAPS_PROJECTION, envelope, pageManagers);
144

    
145
        if(rasterQuery.getClip()!=null){
146
            Buffer completeBuffer = buffer;
147
            envelope  = rasterQuery.getClip();
148
            buffer = bufferManager.createClippedBuffer(completeBuffer, envelope);
149
            DisposeUtils.dispose(completeBuffer);
150
        }
151

    
152
        return buffer;
153
    }
154

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

    
178
    }
179

    
180
    @Override
181
    public int getBands() {
182
        return 4;
183
    }
184

    
185
    @Override
186
    public DataServerExplorer getExplorer() throws ReadException, ValidateDataParametersException {
187
        // TODO Auto-generated method stub
188
        return null;
189
    }
190

    
191
    @Override
192
    public void open() throws OpenException {
193
        for(int i=0; i<getBands(); i++){
194
            this.getBandDescriptor(i).setDataType(DataTypes.BYTE);
195
        }
196
    }
197

    
198
    @Override
199
    public ResourceProvider getResource() {
200
        return null;
201
    }
202

    
203
    @Override
204
    public Object getSourceId() {
205
        return NAME+"-"+getParameters().getDynValue("mapType");
206
    }
207

    
208
    @Override
209
    public String getProviderName() {
210
        return NAME;
211
    }
212

    
213
    @Override
214
    public String getName() {
215
        I18nManager i18nManager = ToolsLocator.getI18nManager();
216
        String mapId = (String) getParameters().getDynValue("mapType");
217
        MapTypes mapType = MapTypes.valueOf(StringUtils.upperCase(mapId));
218

    
219
        return i18nManager.getTranslation("_google_maps")+" "+mapType.toString();
220
    }
221

    
222
    @Override
223
    public String getFullName() {
224
        return NAME+"-"+getParameters().getDynValue("mapType");
225
    }
226

    
227
    public TileStruct getTileStruct() {
228
        if(tileStruct == null){
229
            autoOpen();
230
            tileStruct = new DefaultTileStruct();
231
            tileStruct.setColumnsPerTile(GoogleMapsRasterLibrary.TILE_SIZE);
232
            tileStruct.setRowsPerTile(GoogleMapsRasterLibrary.TILE_SIZE);
233

    
234
            //FIXME: ??
235
//            tileStruct.setProviderName("GTIFF");
236

    
237
            try {
238
                worldExtent = GeometryLocator.getGeometryManager().createEnvelope(-20037508, -20037508, 20037508, 20037508, SUBTYPES.GEOM2D);
239
                tileStruct.setEnvelope(worldExtent);
240

    
241
                Map<Integer, Double> zoomLevels = new HashMap<Integer, Double>();
242

    
243
                double pixelSize = worldExtent.getLength(DIMENSIONS.X)/GoogleMapsRasterLibrary.GOOGLE_MAPS_TILE_SIZE;
244
                for (int zoomLevel = 0; zoomLevel <= GoogleMapsRasterLibrary.MAX_ZOOM_LEVEL; zoomLevel++) {
245
                    zoomLevels.put(zoomLevel, pixelSize);
246
                    pixelSize = pixelSize/2;
247
                }
248

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

    
257
    private GoogleMapsImage getGoogleMapsImage() {
258
        if(this.image == null){
259
            this.image = new GoogleMapsImage(getTileStruct(), this);
260
        }
261
        return this.image;
262
    }
263

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

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

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

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

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

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