// conversion of Steve's quick and dirty ruby approximation of Mercator projection from www.openstreetmap.org public class OSMMercator { protected double clat, clon, dlat, dlon, degrees_per_pixel; protected double tx, ty, bx, by; protected double w, h; protected double QUARTER_PI = Math.PI / 4.0; protected double PIby360 = Math.PI / 360.0; protected double xdiv, ydiv; /** init me with your centre lat/lon, the number of degrees per pixel and the size of your image */ public OSMMercator(double clat, double clon, double degrees_per_pixel, int w, int h) { this.clat = clat; this.clon = clon; this.degrees_per_pixel = degrees_per_pixel; this.w = w; this.h = h; dlon = this.w / 2.0 * degrees_per_pixel; dlat = this.h / 2.0 * degrees_per_pixel * Math.cos(clat * Math.PI / 180.0); tx = xsheet(clon - dlon); ty = ysheet(clat - dlat); bx = xsheet(clon + dlon); by = ysheet(clat + dlat); xdiv = 1.0 / (bx - tx) * w; ydiv = 1.0 / (by - ty) * h; } public double kilometerinpixels() { return 40008.0 / 360.0 * degrees_per_pixel; } // the following two functions will give you the x/y on the entire sheet public double ysheet(double lat) { return Math.log(Math.tan(QUARTER_PI + (lat * PIby360))); } public double xsheet(double lon) { return lon; } // and these two will give you the right points on your image. all the constants can be reduced to speed things up. FIXME public double y(double lat) { return h - ((ysheet(lat) - ty) * ydiv); } public double x(double lon) { return (xsheet(lon) - tx) * xdiv; } public boolean projectable(double lat, double lon) { // top left? bottom right? return lat < clat + dlat && lon > clon - dlon && lat > clat - dlat && lon < clon + dlon; } public String bbox() { double west = clon-dlon; double south = clat-dlat; double east = clon+dlon; double north = clat+dlat; return west + "," + south + "," + east + "," + north; } }