Created
October 13, 2011 13:22
-
-
Save swinton/1284198 to your computer and use it in GitHub Desktop.
MercatorMap.java | Utility class to convert between geo-locations and Cartesian screen coordinates, via tillnagel.com
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Utility class to convert between geo-locations and Cartesian screen coordinates. | |
* Can be used with a bounding box defining the map section. | |
* | |
* (c) 2011 Till Nagel, tillnagel.com | |
*/ | |
public class MercatorMap { | |
public static final float DEFAULT_TOP_LATITUDE = 80; | |
public static final float DEFAULT_BOTTOM_LATITUDE = -80; | |
public static final float DEFAULT_LEFT_LONGITUDE = -180; | |
public static final float DEFAULT_RIGHT_LONGITUDE = 180; | |
/** Horizontal dimension of this map, in pixels. */ | |
protected float mapScreenWidth; | |
/** Vertical dimension of this map, in pixels. */ | |
protected float mapScreenHeight; | |
/** Northern border of this map, in degrees. */ | |
protected float topLatitude; | |
/** Southern border of this map, in degrees. */ | |
protected float bottomLatitude; | |
/** Western border of this map, in degrees. */ | |
protected float leftLongitude; | |
/** Eastern border of this map, in degrees. */ | |
protected float rightLongitude; | |
private float topLatitudeRelative; | |
private float bottomLatitudeRelative; | |
private float leftLongitudeRadians; | |
private float rightLongitudeRadians; | |
public MercatorMap(float mapScreenWidth, float mapScreenHeight) { | |
this(mapScreenWidth, mapScreenHeight, DEFAULT_TOP_LATITUDE, DEFAULT_BOTTOM_LATITUDE, DEFAULT_LEFT_LONGITUDE, DEFAULT_RIGHT_LONGITUDE); | |
} | |
/** | |
* Creates a new MercatorMap with dimensions and bounding box to convert between geo-locations and screen coordinates. | |
* | |
* @param mapScreenWidth Horizontal dimension of this map, in pixels. | |
* @param mapScreenHeight Vertical dimension of this map, in pixels. | |
* @param topLatitude Northern border of this map, in degrees. | |
* @param bottomLatitude Southern border of this map, in degrees. | |
* @param leftLongitude Western border of this map, in degrees. | |
* @param rightLongitude Eastern border of this map, in degrees. | |
*/ | |
public MercatorMap(float mapScreenWidth, float mapScreenHeight, float topLatitude, float bottomLatitude, float leftLongitude, float rightLongitude) { | |
this.mapScreenWidth = mapScreenWidth; | |
this.mapScreenHeight = mapScreenHeight; | |
this.topLatitude = topLatitude; | |
this.bottomLatitude = bottomLatitude; | |
this.leftLongitude = leftLongitude; | |
this.rightLongitude = rightLongitude; | |
this.topLatitudeRelative = getScreenYRelative(topLatitude); | |
this.bottomLatitudeRelative = getScreenYRelative(bottomLatitude); | |
this.leftLongitudeRadians = getRadians(leftLongitude); | |
this.rightLongitudeRadians = getRadians(rightLongitude); | |
} | |
/** | |
* Projects the geo location to Cartesian coordinates, using the Mercator projection. | |
* | |
* @param geoLocation Geo location with (latitude, longitude) in degrees. | |
* @returns The screen coordinates with (x, y). | |
*/ | |
public PVector getScreenLocation(PVector geoLocation) { | |
float latitudeInDegrees = geoLocation.x; | |
float longitudeInDegrees = geoLocation.y; | |
return new PVector(getScreenX(longitudeInDegrees), getScreenY(latitudeInDegrees)); | |
} | |
private float getScreenYRelative(float latitudeInDegrees) { | |
return log(tan(latitudeInDegrees / 360f * PI + PI / 4)); | |
} | |
protected float getScreenY(float latitudeInDegrees) { | |
return mapScreenHeight * (getScreenYRelative(latitudeInDegrees) - topLatitudeRelative) / (bottomLatitudeRelative - topLatitudeRelative); | |
} | |
private float getRadians(float deg) { | |
return deg * PI / 180; | |
} | |
protected float getScreenX(float longitudeInDegrees) { | |
float longitudeInRadians = getRadians(longitudeInDegrees); | |
return mapScreenWidth * (longitudeInRadians - leftLongitudeRadians) / (rightLongitudeRadians - leftLongitudeRadians); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment