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 / GoogleMapsImage.java @ 6903

History | View | Annotate | Download (9.47 KB)

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

    
3
import java.awt.image.BufferedImage;
4
import java.util.HashMap;
5
import java.util.Iterator;
6
import java.util.Map;
7
import java.util.Map.Entry;
8
import java.util.Set;
9

    
10
import org.slf4j.Logger;
11
import org.slf4j.LoggerFactory;
12

    
13
import org.gvsig.fmap.dal.DataStoreParameters;
14
import org.gvsig.fmap.dal.exception.DataException;
15
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
16
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
17
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
18
import org.gvsig.fmap.geom.GeometryLocator;
19
import org.gvsig.fmap.geom.GeometryManager;
20
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
21
import org.gvsig.fmap.geom.exception.CreateGeometryException;
22
import org.gvsig.fmap.geom.primitive.Envelope;
23
import org.gvsig.fmap.geom.primitive.Point;
24
import org.gvsig.googlemaps.lib.api.GoogleMapsLocator;
25
import org.gvsig.googlemaps.lib.api.GoogleMapsManager;
26
import org.gvsig.googlemaps.lib.api.GoogleMapsRequest;
27
import org.gvsig.googlemaps.lib.api.GoogleMapsRequestParams;
28
import org.gvsig.googlemaps.lib.api.exceptions.DownloadingException;
29
import org.gvsig.googlemaps.lib.api.exceptions.URLFormatException;
30
import org.gvsig.raster.lib.buffer.api.Band;
31
import org.gvsig.raster.lib.buffer.api.Buffer;
32
import org.gvsig.raster.lib.buffer.api.BufferLocator;
33
import org.gvsig.raster.lib.buffer.api.TileStruct;
34
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
35
import org.gvsig.tools.ToolsLocator;
36
import org.gvsig.tools.dispose.Disposable;
37
import org.gvsig.tools.dispose.DisposeUtils;
38
import org.gvsig.tools.dispose.impl.AbstractDisposable;
39
import org.gvsig.tools.exception.BaseException;
40
import org.gvsig.tools.locator.LocatorException;
41

    
42

    
43
/**
44
 * @author fdiaz
45
 *
46
 */
47
public class GoogleMapsImage extends AbstractDisposable {
48

    
49
    private static final Logger logger = LoggerFactory.getLogger(GoogleMapsImage.class);
50

    
51
    private TileStruct tileStruct;
52
    private GoogleMapsRasterProvider provider;
53
    private DownloadedTile tile;
54

    
55
    /**
56
     * @param provider
57
     * @param query
58
     * @param tileStruct
59
     */
60
    public GoogleMapsImage(TileStruct tileStruct, GoogleMapsRasterProvider provider) {
61
        this.tileStruct = tileStruct;
62
        this.provider = provider;
63
        this.tile = null;
64
    }
65

    
66
    /**
67
     * @param bandNumber
68
     * @param zoomLevel
69
     * @param structRow
70
     * @param structCol
71
     * @return Band
72
     * @throws CreateEnvelopeException
73
     * @throws CloneNotSupportedException
74
     * @throws ValidateDataParametersException
75
     */
76
    public Band fetchTile(int bandNumber, int zoomLevel, int structRow, int structCol) throws CreateEnvelopeException,
77
        ValidateDataParametersException, CloneNotSupportedException {
78

    
79
        String keyTile = composeKeyForRecentTiles(zoomLevel, structRow, structCol);
80

    
81
        Buffer buffer = null;
82
        if (this.tile != null && this.tile.getKey().equalsIgnoreCase(keyTile) && this.tile.isDownloaded()) {
83
            // Devolver la banda del buffer del tile
84
            logger.info("Devolviendo la banda "+bandNumber+" del buffer del tile "+tile.getKey());
85
            try {
86
                buffer = tile.getBuffer();
87
                Band band = buffer.getBand(bandNumber);
88
                ToolsLocator.getDisposableManager().bind(band);
89
                return band;
90
            } catch (InterruptedException e) {
91
                logger.warn("Can't fetch tile: zoomLevel = " + zoomLevel + ", tileRow = " + structRow
92
                    + ", tileColumn = " + structCol + ", band = " + bandNumber + ".", e);
93
                return null;
94
            }
95
        } else {
96
            this.tile=null;
97
            // Cargar un tile nuevo
98
            Band band = null;
99
            try {
100
                while(this.tile==null || !this.tile.isDownloaded()) {
101
                    tile = requestTile(zoomLevel, structRow, structCol, keyTile);
102
                }
103

    
104
                buffer = tile.getBuffer();
105

    
106
                band = buffer.getBand(bandNumber);
107
                ToolsLocator.getDisposableManager().bind(band);
108
                return band;
109
            } catch (DataException | BufferException | CreateGeometryException | InterruptedException | URLFormatException | DownloadingException e) {
110
                logger.warn("Can't fetch tile: zoomLevel = " + zoomLevel + ", tileRow = " + structRow
111
                    + ", tileColumn = " + structCol + ", band = " + bandNumber + ".", e);
112
                return null;
113
            }
114
        }
115
    }
116

    
117
    private DownloadedTile requestTile(int zoomLevel, int structRow, int structCol, String key) throws CreateEnvelopeException,
118
        CloneNotSupportedException, BufferException, ValidateDataParametersException, DataException, CreateGeometryException, URLFormatException, DownloadingException {
119

    
120
        Double pixelSize = this.tileStruct.getPixelSizePerZoomLevel().get(zoomLevel);
121

    
122
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
123

    
124
        Envelope structExtent = this.tileStruct.getEnvelope();
125
        int rowsPerTile = this.tileStruct.getRowsPerTile();
126
        int columnsPerTile = this.tileStruct.getColumnsPerTile();
127

    
128
        double minX = Math.max(structExtent.getMinimum(DIMENSIONS.X) + (structCol * (pixelSize * columnsPerTile)),structExtent.getMinimum(DIMENSIONS.X));
129
        double minY = Math.max(structExtent.getMaximum(DIMENSIONS.Y) - ((structRow + 1) * (pixelSize * rowsPerTile)),structExtent.getMinimum(DIMENSIONS.Y));
130
        double maxX = Math.min(structExtent.getMinimum(DIMENSIONS.X) + ((structCol + 1) * (pixelSize * columnsPerTile)),structExtent.getMaximum(DIMENSIONS.X));
131
        double maxY = Math.min(structExtent.getMaximum(DIMENSIONS.Y) - (structRow * (pixelSize * rowsPerTile)),structExtent.getMaximum(DIMENSIONS.Y));
132
        Envelope envelope = geomManager.createEnvelope(minX, minY, maxX, maxY, SUBTYPES.GEOM2D);
133
        Point center;
134

    
135
        center = geomManager.createPoint(envelope.getCenter(DIMENSIONS.X), envelope.getCenter(DIMENSIONS.Y), SUBTYPES.GEOM2D);
136

    
137
        GoogleMapsManager googleMapsManager = GoogleMapsLocator.getManager();
138
        GoogleMapsRequestParams requestParams = googleMapsManager.createRequestParams();
139

    
140
        DataStoreParameters storeParameters = provider.getParameters();
141
        requestParams.setHasApiKey((Boolean) storeParameters.getDynValue("hasApiKey"));
142
        requestParams.setApiKey((String) storeParameters.getDynValue("apiKey"));
143
        requestParams.setLanguage((String) storeParameters.getDynValue("language"));
144
        requestParams.setRegion((String) storeParameters.getDynValue("region"));
145
        requestParams.setURL("http://maps.google.com/maps/api/staticmap?");
146
        requestParams.setMapType((String) storeParameters.getDynValue("mapType"));
147
        requestParams.setFormat((String) storeParameters.getDynValue("format"));
148

    
149
        GoogleMapsRequest googleRequest=googleMapsManager.createRequest(requestParams);
150
        DownloadedTile downloadedTile = new DownloadedTile(key, envelope);
151
        downloadedTile.setImage(googleRequest.getTile(center, zoomLevel, (int)Math.round(envelope.getLength(DIMENSIONS.X)/pixelSize), (int)Math.round(envelope.getLength(DIMENSIONS.Y)/pixelSize)));
152

    
153
        return downloadedTile;
154
    }
155

    
156
    private String composeKeyForRecentTiles(int zoomLevel, int structRow, int structCol) {
157
        StringBuilder builder = new StringBuilder();
158
        builder.append(zoomLevel);
159
        builder.append(":");
160
        builder.append(structCol);
161
        builder.append(":");
162
        builder.append(structRow);
163
        return builder.toString();
164
    }
165

    
166
    private class DownloadedTile extends AbstractDisposable { //implements GoogleMapsRequestListener {
167

    
168
        private org.gvsig.raster.lib.buffer.api.Buffer buffer;
169
        long lastAccess;
170
        private String key;
171
        private Envelope envelope;
172
        private boolean downloaded;
173

    
174
        public DownloadedTile(String key, Envelope envelope) {
175
            this.key = key;
176
            this.envelope = envelope;
177
            lastAccess = System.currentTimeMillis();
178
            this.downloaded = false;
179
        }
180

    
181
        public String getKey() {
182
            return key;
183
        }
184

    
185
        public synchronized org.gvsig.raster.lib.buffer.api.Buffer getBuffer() throws InterruptedException {
186
            lastAccess = System.currentTimeMillis();
187
            while(!isDownloaded()){
188
                this.wait();
189
            }
190
            return buffer;
191
        }
192

    
193
        public long getLastAccess() {
194
            return lastAccess;
195
        }
196

    
197
        @Override
198
        protected void finalize() throws Throwable {
199
            super.finalize();
200
        }
201

    
202
        public synchronized void setImage(BufferedImage img) {
203

    
204
            downloaded = false;
205

    
206
            try {
207

    
208
                this.buffer =
209
                    BufferLocator.getBufferManager().createBuffer(img, GoogleMapsRasterProvider.GOOGLE_MAPS_PROJECTION,
210
                        this.envelope);
211

    
212
            } catch (LocatorException | BufferException e) {
213
                logger.warn("Can't create buffer to load downloaded image.", e);
214
            }
215

    
216
            this.downloaded = true;
217
            this.notify();
218
        }
219

    
220
        @Override
221
        protected void doDispose() throws BaseException {
222
            DisposeUtils.dispose(buffer);
223
            buffer = null;
224
        }
225

    
226

    
227
        public boolean isDownloaded(){
228
            return this.downloaded;
229
        }
230
    }
231

    
232
    @Override
233
    protected void doDispose() throws BaseException {
234
        if(this.tile != null) {
235
            DisposeUtils.dispose(this.tile);
236
        }
237
        DisposeUtils.dispose((Disposable) tileStruct);
238
        tileStruct = null;
239
    }
240

    
241
}