/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2011, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.googlemaps.model; import java.awt.Dimension; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Map; import javax.imageio.ImageIO; import org.geotoolkit.client.Request; import org.geotoolkit.client.map.CachedPyramidSet; import org.geotoolkit.storage.coverage.DefaultPyramid; import org.geotoolkit.storage.coverage.GridMosaic; import org.geotoolkit.storage.coverage.PyramidSet; import org.apache.sis.geometry.GeneralDirectPosition; import org.apache.sis.geometry.GeneralEnvelope; import org.geotoolkit.googlemaps.GetMapRequest; import org.geotoolkit.googlemaps.GoogleCoverageReference; import org.geotoolkit.googlemaps.StaticGoogleMapsClient; import org.apache.sis.referencing.CRS; import org.apache.sis.storage.DataStoreException; import org.opengis.geometry.DirectPosition; import org.opengis.geometry.Envelope; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.util.FactoryException; /** * * @author Johann Sorel (Geomatys) * @module */ public class GoogleMapsPyramidSet extends CachedPyramidSet{ public static final int BASE_TILE_SIZE = 256; public static final CoordinateReferenceSystem GOOGLE_MERCATOR; public static final Envelope MERCATOR_EXTEND; public static final BufferedImage OVERLOAD; /** * Resolution at zoom 0 level. in meter by pixel. */ public static final double ZOOM_ZERO_RESOLUTION; static { try { GOOGLE_MERCATOR = CRS.forCode("EPSG:3857"); } catch (FactoryException ex) { throw new RuntimeException(ex); } //this is not an exact extent, google once again do not respect anything //MERCATOR_EXTEND = CRS.getEnvelope(GoogleMapsUtilities.GOOGLE_MERCATOR); MERCATOR_EXTEND = new GeneralEnvelope(GOOGLE_MERCATOR); ((GeneralEnvelope)MERCATOR_EXTEND).setRange(0, -20037508.342789244d, 20037508.342789244d); ((GeneralEnvelope)MERCATOR_EXTEND).setRange(1, -20037508.342789244d, 20037508.342789244d); ZOOM_ZERO_RESOLUTION = MERCATOR_EXTEND.getSpan(0) / BASE_TILE_SIZE; try { OVERLOAD = ImageIO.read(GoogleMapsPyramidSet.class.getResourceAsStream("/org/geotoolkit/googlemaps/staticmap.png")); } catch (IOException ex) { throw new RuntimeException(ex); } } private final GoogleCoverageReference ref; private final String mapType; public GoogleMapsPyramidSet(final GoogleCoverageReference ref, final boolean cacheImage) throws DataStoreException{ super((StaticGoogleMapsClient)ref.getStore(),true,cacheImage); this.ref = ref; this.mapType = ref.getName().tip().toString(); final int maxScale; if (GetMapRequest.TYPE_HYBRID.equalsIgnoreCase(mapType)) { maxScale = 18; } else if (GetMapRequest.TYPE_ROADMAP.equalsIgnoreCase(mapType)) { maxScale = 18; } else if (GetMapRequest.TYPE_SATELLITE.equalsIgnoreCase(mapType)) { maxScale = 18; } else if (GetMapRequest.TYPE_TERRAIN.equalsIgnoreCase(mapType)) { maxScale = 18; } else { throw new DataStoreException("Unknowned google maps layer : " + mapType); } final DefaultPyramid pyramid = new DefaultPyramid(this, GOOGLE_MERCATOR); final int tileWidth = (int) BASE_TILE_SIZE; final int tileHeight = (int) BASE_TILE_SIZE; final Envelope extent = MERCATOR_EXTEND; final GeneralDirectPosition upperLeft = new GeneralDirectPosition(GOOGLE_MERCATOR); upperLeft.setOrdinate(0, extent.getMinimum(0)); upperLeft.setOrdinate(1, extent.getMaximum(1)); final double scale0Resolution = extent.getSpan(0) / BASE_TILE_SIZE; for(int i=0; i<=maxScale; i++){ final int size = (int) Math.pow(2, i); final double scale = scale0Resolution / size; final GoogleMapsMosaic mosaic = new GoogleMapsMosaic( pyramid, upperLeft, new Dimension(size,size), new Dimension(tileHeight, tileWidth), scale, i); pyramid.getMosaicsInternal().add(mosaic); } getPyramids().add(pyramid); } @Override protected StaticGoogleMapsClient getServer() { return (StaticGoogleMapsClient)super.getServer(); } @Override public Request getTileRequest(GridMosaic mosaic, int col, int row, Map hints) throws DataStoreException { final int zoom = ((GoogleMapsMosaic)mosaic).getScaleLevel(); final GetMapRequest request = ref.createGetMap(); Object format = hints.get(PyramidSet.HINT_FORMAT); if(format == null){ //set a default value format = "image/png"; } request.setFormat(format.toString()); request.setMapType(mapType); request.setDimension(new Dimension(BASE_TILE_SIZE, BASE_TILE_SIZE)); request.setZoom(zoom); final DirectPosition position = getCenter(zoom, col, row); request.setCenter(position); return request; } /** * Returns resolution at zoom given level. in meter by pixel. * @param zoom * @return */ public static double getZoomResolution(final int zoom){ return ZOOM_ZERO_RESOLUTION * Math.pow(0.5d, zoom); } public static DirectPosition getCenter(final int zoom, final int col, final int row){ final GeneralDirectPosition position = new GeneralDirectPosition(GOOGLE_MERCATOR); //we look for the center, like searching for a corner if we had two times more cells final double zoomRes = getZoomResolution(zoom + 1); position.setOrdinate(0, MERCATOR_EXTEND.getMinimum(0) + zoomRes* BASE_TILE_SIZE * ( (col)*2 + 1) ); position.setOrdinate(1, MERCATOR_EXTEND.getMaximum(1) - zoomRes* BASE_TILE_SIZE * ( (row)*2 + 1) ); return position; } }