// Created by plusminus on 17:53:07 - 25.09.2008
package org.andnav.osm.views.util;
import org.andnav.osm.util.BoundingBoxE6;
import org.andnav.osm.views.util.constants.OpenStreetMapViewConstants;
import com.robert.maps.applib.utils.OSGB36;
/**
*
* @author Nicolas Gramlich
*
*/
public class Util implements OpenStreetMapViewConstants{
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
public static int[] getMapTileFromCoordinates(final int aLat, final int aLon, final int zoom, final int[] reuse, final int aProjection) {
return getMapTileFromCoordinates(aLat / 1E6, aLon / 1E6, zoom, reuse, aProjection);
}
public static int[] getMapTileFromCoordinates(final double aLat, final double aLon, final int zoom, final int[] aUseAsReturnValue, final int aProjection) {
final int[] out = (aUseAsReturnValue != null) ? aUseAsReturnValue : new int[2];
if (aProjection == 3) {
final double[] OSRef = OSGB36.LatLon2OSGB(aLat, aLon);
out[0] = (int) ((1 - OSRef[0] / 1000000)*OpenSpaceUpperBoundArray[zoom - 7]);
out[1] = (int) ((OSRef[1] / 1000000)*OpenSpaceUpperBoundArray[zoom - 7]);
} else {
if (aProjection == 1)
out[MAPTILE_LATITUDE_INDEX] = (int) Math.floor((1 - Math
.log(Math.tan(aLat * Math.PI / 180) + 1
/ Math.cos(aLat * Math.PI / 180))
/ Math.PI)
/ 2 * (1 << zoom));
else {
final double E2 = (double) aLat * Math.PI / 180;
final long sradiusa = 6378137;
final long sradiusb = 6356752;
final double J2 = (double) Math.sqrt(sradiusa * sradiusa
- sradiusb * sradiusb)
/ sradiusa;
final double M2 = (double) Math.log((1 + Math.sin(E2))
/ (1 - Math.sin(E2)))
/ 2
- J2
* Math.log((1 + J2 * Math.sin(E2))
/ (1 - J2 * Math.sin(E2))) / 2;
final double B2 = (double) (1 << zoom);
out[MAPTILE_LATITUDE_INDEX] = (int) Math.floor(B2 / 2 - M2 * B2
/ 2 / Math.PI);
}
out[MAPTILE_LONGITUDE_INDEX] = (int) Math.floor((aLon + 180) / 360
* (1 << zoom));
}
return out;
}
// Conversion of a MapTile to a BoudingBox
public static BoundingBoxE6 getBoundingBoxFromMapTile(final int[] aMapTile, final int zoom, final int aProjection) {
final int y = aMapTile[MAPTILE_LATITUDE_INDEX];
final int x = aMapTile[MAPTILE_LONGITUDE_INDEX];
if(aProjection == 3){
final double[] LatLon0 = OSGB36.OSGB2LatLon(
(double)((OpenSpaceUpperBoundArray[zoom - 7] - y - 1) * 1000000
/ OpenSpaceUpperBoundArray[zoom - 7]), (double)(x * 1000000
/ OpenSpaceUpperBoundArray[zoom - 7]));
final double[] LatLon1 = OSGB36.OSGB2LatLon(
(double)((OpenSpaceUpperBoundArray[zoom - 7] - y - 1 + 1) * 1000000
/ OpenSpaceUpperBoundArray[zoom - 7]), (double)((x + 1) * 1000000
/ OpenSpaceUpperBoundArray[zoom - 7]));
return new BoundingBoxE6(LatLon1[0], LatLon1[1], LatLon0[0], LatLon0[1]);
} else
return new BoundingBoxE6(tile2lat(y, zoom, aProjection), tile2lon(x + 1, zoom), tile2lat(y + 1, zoom, aProjection), tile2lon(x, zoom));
}
private static double tile2lon(int x, int aZoom) {
return (x / Math.pow(2.0, aZoom) * 360.0) - 180;
}
private static double tile2lat(int y, int aZoom, final int aProjection) {
if (aProjection == 1) {
final double n = Math.PI - ((2.0 * Math.PI * y) / Math.pow(2.0, aZoom));
//final double n1 = 180.0 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
return 180.0 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
//return 180 / Math.PI * (2 * Math.atan(Math.exp(a*Math.PI/180)) - Math.PI/2); // http://wiki.openstreetmap.org/wiki/Mercator
} else {
final double y1 = 20037508.342789 - 20037508.342789 * 2 / (1 << aZoom) * y;
final double r_major = 6378137.0; //Equatorial Radius, WGS84
final double r_minor = 6356752.314245179; //defined as constant
double ts = Math.exp ( -y1 / r_major);
double phi = Math.PI/2 - 2 * Math.atan(ts);
double dphi = 1.0;
int i;
for (i = 0; Math.abs(dphi) > 0.000000001 && i < 15; i++) {
double con = (Math.sqrt(1.0 - (r_minor/r_major * r_minor/r_major))) * Math.sin (phi);
dphi = Math.PI/2 - 2 * Math.atan (ts * Math.pow((1.0 - con) / (1.0 + con), (0.5 * (Math.sqrt(1.0 - (r_minor/r_major * r_minor/r_major)))))) - phi;
phi += dphi;
}
return phi / (Math.PI / 180.0);
/*
final double MerkElipsK = 0.0000001;
final long sradiusa = 6378137;
final long sradiusb = 6356752;
final double FExct = (double) Math.sqrt(sradiusa * sradiusa - sradiusb * sradiusb) / sradiusa;
final int TilesAtZoom = 1 << aZoom;
double result = (y - TilesAtZoom / 2) / -(TilesAtZoom / (2 * Math.PI));
result = (2 * Math.atan(Math.exp(result)) - Math.PI / 2) * 180 / Math.PI;
double Zu = result / (180 / Math.PI);
double yy = ((y) - TilesAtZoom / 2);
double Zum1 = Zu;
Zu = Math.asin(1 - ((1 + Math.sin(Zum1)) * Math.pow(1 - FExct * Math.sin(Zum1), FExct))
/ (Math.exp((2 * yy) / -(TilesAtZoom / (2 * Math.PI))) * Math.pow(1 + FExct * Math.sin(Zum1), FExct)));
while (Math.abs(Zum1 - Zu) >= MerkElipsK) {
Zum1 = Zu;
Zu = Math.asin(1 - ((1 + Math.sin(Zum1)) * Math.pow(1 - FExct * Math.sin(Zum1), FExct))
/ (Math.exp((2 * yy) / -(TilesAtZoom / (2 * Math.PI))) * Math.pow(1 + FExct * Math.sin(Zum1), FExct)));
}
if (Zu == Float.NaN)
Zu = 0.0;
result = Zu * 180 / Math.PI;
return result;
*/
}
}
public static int x2lon(int x, int aZoom, final int MAPTILE_SIZEPX) {
int px = MAPTILE_SIZEPX * (1 << aZoom);
if (x < 0)
x = px + x;
if (x > px)
x = x - px;
return (int) (1E6 * (((double)x / px * 360.0) - 180));
}
public static double y2lat(int y, int aZoom, final int MAPTILE_SIZEPX) {
// final int aProjection = 1;
// if (aProjection == 1) {
final double n = Math.PI
- ((2.0 * Math.PI * y) / MAPTILE_SIZEPX * Math.pow(2.0, aZoom));
return 180.0 / Math.PI
* Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
// } else {
// final double MerkElipsK = 0.0000001;
// final long sradiusa = 6378137;
// final long sradiusb = 6356752;
// final double FExct = (double) Math.sqrt(sradiusa * sradiusa
// - sradiusb * sradiusb)
// / sradiusa;
// final int TilesAtZoom = 1 << aZoom;
// double result = (y - TilesAtZoom / 2)
// / -(TilesAtZoom / (2 * Math.PI));
// result = (2 * Math.atan(Math.exp(result)) - Math.PI / 2) * 180
// / Math.PI;
// double Zu = result / (180 / Math.PI);
// double yy = ((y) - TilesAtZoom / 2);
//
// double Zum1 = Zu;
// Zu = Math
// .asin(1
// - ((1 + Math.sin(Zum1)) * Math.pow(1 - FExct
// * Math.sin(Zum1), FExct))
// / (Math.exp((2 * yy)
// / -(TilesAtZoom / (2 * Math.PI))) * Math
// .pow(1 + FExct * Math.sin(Zum1), FExct)));
// while (Math.abs(Zum1 - Zu) >= MerkElipsK) {
// Zum1 = Zu;
// Zu = Math
// .asin(1
// - ((1 + Math.sin(Zum1)) * Math.pow(1 - FExct
// * Math.sin(Zum1), FExct))
// / (Math.exp((2 * yy)
// / -(TilesAtZoom / (2 * Math.PI))) * Math
// .pow(1 + FExct * Math.sin(Zum1), FExct)));
// }
//
// result = Zu * 180 / Math.PI;
//
// return result;
// }
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}