/* * GeoSolutions - MapstoreMobile - GeoSpatial Framework on Android based devices * Copyright (C) 2014 GeoSolutions (www.geo-solutions.it) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package it.geosolutions.android.map.utils; import org.mapsforge.android.maps.Projection; import org.mapsforge.core.model.GeoPoint; import org.mapsforge.core.util.MercatorProjection; import android.graphics.Point; /** * Utility Class to convert WebMercator and Geographic coordinates * Waiting for integration of a mor complex library to do that * CHECK THIS CLASS results of toGeographicX and Y is incorrect! * @author Lorenzo Natali (lorenzo.natali@geo-solutions.it * */ public class ProjectionUtils { /** * Convert a EPSG:900913 longitude (meeters) into geographic WGS:84 (degrees) * @param mercatorX_lon the longitude in Mercator projection * @return the longitude in WGS84 */ public static double toGeographicX( double mercatorX_lon){ if ((Math.abs(mercatorX_lon) > MercatorProjection.EARTH_CIRCUMFERENCE/2) ) throw new IllegalArgumentException(); double x = mercatorX_lon; double num3 = x / 6378137.0; double num4 = num3 * 57.295779513082323; double num5 = Math.floor((double)((num4 + 180.0) / 360.0)); return num4 - (num5 * 360.0); } /** * Convert a EPSG:900913 latitude (meeters) into geographic EPSG:4326 (degrees) * @param mercatorY_lat the latitude in Mercator projection * @return the latitude in WGS84 */ public static double toGeographicY( double mercatorY_lat){ if ((Math.abs(mercatorY_lat) > MercatorProjection.EARTH_CIRCUMFERENCE/2) ){ throw new IllegalArgumentException(); } double y = mercatorY_lat; double num7 = 1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * y) / 6378137.0))); return num7 * 57.295779513082323; } /** * Convert a geographic longitude WGS84 (degrees) into EPSG:900913 latitude (meeters) * @param lon the longitude to convert * @return longitude in meeters (EPSG:900913) */ public static double toWebMercatorX( double lon){ //TODO optimize if (Math.abs(lon) > 180 ){ throw new IllegalArgumentException(); } double num = lon * 0.017453292519943295; return 6378137.0 * num; } /** * Convert a geographic latitude WGS84 (degrees) into EPSG:900913 latitude (meeters) * @param lat latitude to convert * @return latitude in meeters (EPSG:900913) */ public static double toWebMercatorY(double lat) { //TODO optimize if ( Math.abs(lat) > 90){ throw new IllegalArgumentException(); } double a = lat * 0.017453292519943295; return 3189068.5 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a))); } /** * Gets the left-up corner and returns the point on the canvas to draw to * @param dp the top left corner of the map * @param projection the mapview projection * @param drawZoomLevel the current zoom level * @return array of pixels [x,y] */ public static long[] getDrawPoint(GeoPoint dp, Projection projection, byte drawZoomLevel){ long drawX = (long) MercatorProjection.longitudeToPixelX(dp.longitude, drawZoomLevel); long drawY = (long) MercatorProjection.latitudeToPixelY(dp.latitude, drawZoomLevel); Point p = new Point(0,0); projection.toPixels(new GeoPoint(MercatorProjection.LATITUDE_MAX,-180), p); if(p.x >0){ drawX -=p.x; } if(p.y>0){ drawY-=p.y; } return new long[]{drawX,drawY}; } /** * Returns the point on the mapView of the top left point of the Mercator Left top * @param projection * @param zoomLevel * @return */ public static long[] getMapLeftTopPoint(Projection projection) { Point p = new Point(0,0); projection.toPixels(new GeoPoint(MercatorProjection.LATITUDE_MAX,-180), p); return new long[]{p.x,p.y}; } /** * Returns the point on the mapView of the bottom point of the Mercator bottom right * @param projection * @param zoomLevel * @return */ public static long[] getMapRightBottom(Projection projection){ Point p = new Point(0,0); projection.toPixels(new GeoPoint(MercatorProjection.LATITUDE_MIN,180), p); return new long[]{p.x,p.y}; } /** * Calulate the size of a WMS request getting proper width/height from the projection * @param width * @param height * @param projection * @return */ public static long[] calculateMapSize(long width,long height,Projection projection){ long[] lt = getMapLeftTopPoint(projection); long[] rb = getMapRightBottom(projection); long[] out =new long[2]; if(rb[0] < width){ width = rb[0]; } if(lt[0] > 0){ out[0] = width -lt[0]; }else{ out[0] = width; } if(rb[1] < height){ height = rb[1]; } if(lt[1] > 0){ out[1] = height -lt[1]; }else{ out[1] = height; } return out; } }