-use absolute x/y position and scale in MapPosition
- scale calculations look much nicer now, better always use 'double' unless you are sure about precision required - finally got rid of zoomLevel relative coordinates - cleanup MapPosition and MercatorProjection API functions
This commit is contained in:
@@ -15,78 +15,73 @@
|
||||
*/
|
||||
package org.oscim.core;
|
||||
|
||||
import org.oscim.utils.FastMath;
|
||||
|
||||
/** A MapPosition Container. */
|
||||
public class MapPosition {
|
||||
public final static int MAX_ZOOMLEVEL = 20;
|
||||
public final static int MIN_ZOOMLEVEL = 2;
|
||||
|
||||
public double lon;
|
||||
public double lat;
|
||||
/** projected position x 0..1 */
|
||||
public double x;
|
||||
/** projected position y 0..1 */
|
||||
public double y;
|
||||
/** absolute scale */
|
||||
public double scale;
|
||||
|
||||
public double absX;
|
||||
public double absY;
|
||||
public double absScale;
|
||||
|
||||
public float scale;
|
||||
/** rotation angle */
|
||||
public float angle;
|
||||
/** perspective tile */
|
||||
public float tilt;
|
||||
|
||||
// map center in tile coordinates of current zoom-level
|
||||
public double x;
|
||||
public double y;
|
||||
// to be removed
|
||||
// FastMath.log2((int) scale)
|
||||
public int zoomLevel;
|
||||
|
||||
public MapPosition() {
|
||||
this.zoomLevel = (byte) 1;
|
||||
this.scale = 1;
|
||||
this.lat = 0;
|
||||
this.lon = 0;
|
||||
this.x = 0.5;
|
||||
this.y = 0.5;
|
||||
this.zoomLevel = 1;
|
||||
this.angle = 0;
|
||||
this.x = MercatorProjection.longitudeToPixelX(this.lon, zoomLevel);
|
||||
this.y = MercatorProjection.latitudeToPixelY(this.lat, zoomLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param geoPoint
|
||||
* the map position.
|
||||
* @param zoomLevel
|
||||
* the zoom level.
|
||||
* @param scale
|
||||
* ...
|
||||
*/
|
||||
public MapPosition(GeoPoint geoPoint, byte zoomLevel, float scale) {
|
||||
public void setZoomLevel(int zoomLevel) {
|
||||
this.zoomLevel = zoomLevel;
|
||||
this.scale = scale;
|
||||
this.lat = geoPoint.getLatitude();
|
||||
this.lon = geoPoint.getLongitude();
|
||||
this.angle = 0;
|
||||
this.x = MercatorProjection.longitudeToPixelX(this.lon, zoomLevel);
|
||||
this.y = MercatorProjection.latitudeToPixelY(this.lat, zoomLevel);
|
||||
this.scale = 1 << zoomLevel;
|
||||
}
|
||||
|
||||
public MapPosition(double latitude, double longitude, int zoomLevel, float scale,
|
||||
float angle) {
|
||||
this.zoomLevel = zoomLevel;
|
||||
public void setScale(double scale) {
|
||||
this.zoomLevel = FastMath.log2((int) scale);
|
||||
this.scale = scale;
|
||||
this.lat = latitude;
|
||||
this.lon = longitude;
|
||||
this.angle = angle;
|
||||
this.x = MercatorProjection.longitudeToPixelX(longitude, zoomLevel);
|
||||
this.y = MercatorProjection.latitudeToPixelY(latitude, zoomLevel);
|
||||
}
|
||||
|
||||
public void setPosition(GeoPoint geoPoint){
|
||||
setPosition(geoPoint.getLatitude(), geoPoint.getLongitude());
|
||||
}
|
||||
|
||||
public void setPosition(double latitude, double longitude) {
|
||||
latitude = MercatorProjection.limitLatitude(latitude);
|
||||
longitude = MercatorProjection.limitLongitude(longitude);
|
||||
this.x = MercatorProjection.longitudeToX(longitude);
|
||||
this.y = MercatorProjection.latitudeToY(latitude);
|
||||
}
|
||||
|
||||
public void copy(MapPosition other) {
|
||||
this.zoomLevel = other.zoomLevel;
|
||||
this.scale = other.scale;
|
||||
this.lat = other.lat;
|
||||
this.lon = other.lon;
|
||||
this.angle = other.angle;
|
||||
this.scale = other.scale;
|
||||
this.x = other.x;
|
||||
this.y = other.y;
|
||||
}
|
||||
|
||||
public void setFromLatLon(double latitude, double longitude, int zoomLevel){
|
||||
this.zoomLevel = zoomLevel;
|
||||
this.x = MercatorProjection.longitudeToPixelX(longitude, zoomLevel);
|
||||
this.y = MercatorProjection.latitudeToPixelY(latitude, zoomLevel);
|
||||
public double getZoomScale() {
|
||||
return scale / (1 << zoomLevel);
|
||||
}
|
||||
|
||||
public GeoPoint getGeoPoint() {
|
||||
return new GeoPoint(MercatorProjection.toLatitude(y),
|
||||
MercatorProjection.toLongitude(x));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,11 +89,11 @@ public class MapPosition {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("MapPosition [");
|
||||
builder.append("lat=");
|
||||
builder.append(this.lat);
|
||||
builder.append(MercatorProjection.toLatitude(y));
|
||||
builder.append(", lon=");
|
||||
builder.append(this.lon);
|
||||
builder.append(MercatorProjection.toLongitude(x));
|
||||
builder.append(", zoomLevel=");
|
||||
builder.append(this.zoomLevel);
|
||||
builder.append(zoomLevel);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.oscim.core;
|
||||
|
||||
|
||||
/**
|
||||
* An implementation of the spherical Mercator projection.
|
||||
*/
|
||||
@@ -61,28 +60,6 @@ public final class MercatorProjection {
|
||||
/ ((long) Tile.TILE_SIZE << zoomLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a latitude coordinate (in degrees) to a pixel Y coordinate at a
|
||||
* certain zoom level.
|
||||
*
|
||||
* @param latitude
|
||||
* the latitude coordinate that should be converted.
|
||||
* @param zoomLevel
|
||||
* the zoom level at which the coordinate should be converted.
|
||||
* @return the pixel Y coordinate of the latitude value.
|
||||
*/
|
||||
public static double latitudeToPixelY(double latitude, int zoomLevel) {
|
||||
double sinLatitude = Math.sin(latitude * (Math.PI / 180));
|
||||
return (0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI))
|
||||
* ((long) Tile.TILE_SIZE << zoomLevel);
|
||||
}
|
||||
|
||||
public static double latitudeToPixelY(MapPosition mapPosition) {
|
||||
double sinLatitude = Math.sin(mapPosition.lat * (Math.PI / 180));
|
||||
return (0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI))
|
||||
* ((long) Tile.TILE_SIZE << mapPosition.zoomLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Projects a longitude coordinate (in degrees) to the range [0.0,1.0]
|
||||
*
|
||||
@@ -95,18 +72,23 @@ public final class MercatorProjection {
|
||||
return 0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI);
|
||||
}
|
||||
|
||||
public static double toLatitude(double y) {
|
||||
return 90 - 360 * Math.atan(Math.exp((y - 0.5) * (2 * Math.PI))) / Math.PI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a latitude coordinate (in degrees) to a tile Y number at a
|
||||
* certain zoom level.
|
||||
* Projects a longitude coordinate (in degrees) to the range [0.0,1.0]
|
||||
*
|
||||
* @param latitude
|
||||
* the latitude coordinate that should be converted.
|
||||
* @param zoomLevel
|
||||
* the zoom level at which the coordinate should be converted.
|
||||
* @return the tile Y number of the latitude value.
|
||||
* @param longitude
|
||||
* the longitude coordinate that should be converted.
|
||||
* @return the position .
|
||||
*/
|
||||
public static long latitudeToTileY(double latitude, int zoomLevel) {
|
||||
return pixelYToTileY(latitudeToPixelY(latitude, zoomLevel), zoomLevel);
|
||||
public static double longitudeToX(double longitude) {
|
||||
return (longitude + 180) / 360;
|
||||
}
|
||||
|
||||
public static double toLongitude(double x) {
|
||||
return 360 * (x - 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,51 +117,6 @@ public final class MercatorProjection {
|
||||
return Math.max(Math.min(longitude - 360, LONGITUDE_MAX), LONGITUDE_MIN);
|
||||
|
||||
return longitude;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a longitude coordinate (in degrees) to a pixel X coordinate at a
|
||||
* certain zoom level.
|
||||
*
|
||||
* @param longitude
|
||||
* the longitude coordinate that should be converted.
|
||||
* @param zoomLevel
|
||||
* the zoom level at which the coordinate should be converted.
|
||||
* @return the pixel X coordinate of the longitude value.
|
||||
*/
|
||||
public static double longitudeToPixelX(double longitude,int zoomLevel) {
|
||||
return (longitude + 180) / 360 * ((long) Tile.TILE_SIZE << zoomLevel);
|
||||
}
|
||||
|
||||
public static double longitudeToPixelX(MapPosition mapPosition) {
|
||||
return (mapPosition.lon + 180) / 360
|
||||
* ((long) Tile.TILE_SIZE << mapPosition.zoomLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Projects a longitude coordinate (in degrees) to the range [0.0,1.0]
|
||||
*
|
||||
* @param longitude
|
||||
* the longitude coordinate that should be converted.
|
||||
* @return the position .
|
||||
*/
|
||||
public static double longitudeToX(double longitude) {
|
||||
return (longitude + 180) / 360;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a longitude coordinate (in degrees) to the tile X number at a
|
||||
* certain zoom level.
|
||||
*
|
||||
* @param longitude
|
||||
* the longitude coordinate that should be converted.
|
||||
* @param zoomLevel
|
||||
* the zoom level at which the coordinate should be converted.
|
||||
* @return the tile X number of the longitude value.
|
||||
*/
|
||||
public static long longitudeToTileX(double longitude, int zoomLevel) {
|
||||
return pixelXToTileX(longitudeToPixelX(longitude, zoomLevel), zoomLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,25 +133,18 @@ public final class MercatorProjection {
|
||||
return 360 * ((pixelX / ((long) Tile.TILE_SIZE << zoomLevel)) - 0.5);
|
||||
}
|
||||
|
||||
public static double toLongitude(double pixelX) {
|
||||
return 360 * (pixelX - 0.5);
|
||||
}
|
||||
|
||||
public static double toLongitude(double pixelX, double scale) {
|
||||
return 360 * ((pixelX / scale) - 0.5);
|
||||
}
|
||||
/**
|
||||
* Converts a pixel X coordinate to the tile X number.
|
||||
* Converts a longitude coordinate (in degrees) to a pixel X coordinate at a
|
||||
* certain zoom level.
|
||||
*
|
||||
* @param pixelX
|
||||
* the pixel X coordinate that should be converted.
|
||||
* @param longitude
|
||||
* the longitude coordinate that should be converted.
|
||||
* @param zoomLevel
|
||||
* the zoom level at which the coordinate should be converted.
|
||||
* @return the tile X number.
|
||||
* @return the pixel X coordinate of the longitude value.
|
||||
*/
|
||||
public static int pixelXToTileX(double pixelX, int zoomLevel) {
|
||||
return (int) Math.min(Math.max(pixelX / Tile.TILE_SIZE, 0),
|
||||
Math.pow(2, zoomLevel) - 1);
|
||||
public static double longitudeToPixelX(double longitude, int zoomLevel) {
|
||||
return (longitude + 180) / 360 * ((long) Tile.TILE_SIZE << zoomLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,69 +162,22 @@ public final class MercatorProjection {
|
||||
return 90 - 360 * Math.atan(Math.exp(-y * (2 * Math.PI))) / Math.PI;
|
||||
}
|
||||
|
||||
public static double toLatitude(double pixelY) {
|
||||
double y = 0.5 - pixelY;
|
||||
return 90 - 360 * Math.atan(Math.exp(-y * (2 * Math.PI))) / Math.PI;
|
||||
}
|
||||
|
||||
public static double toLatitude(double pixelY, double scale) {
|
||||
double y = 0.5 - pixelY / scale;
|
||||
return 90 - 360 * Math.atan(Math.exp(-y * (2 * Math.PI))) / Math.PI;
|
||||
}
|
||||
/**
|
||||
* Converts a pixel Y coordinate to the tile Y number.
|
||||
* Converts a latitude coordinate (in degrees) to a pixel Y coordinate at a
|
||||
* certain zoom level.
|
||||
*
|
||||
* @param pixelY
|
||||
* the pixel Y coordinate that should be converted.
|
||||
* @param latitude
|
||||
* the latitude coordinate that should be converted.
|
||||
* @param zoomLevel
|
||||
* the zoom level at which the coordinate should be converted.
|
||||
* @return the tile Y number.
|
||||
* @return the pixel Y coordinate of the latitude value.
|
||||
*/
|
||||
public static int pixelYToTileY(double pixelY, int zoomLevel) {
|
||||
return (int) Math.min(Math.max(pixelY / Tile.TILE_SIZE, 0),
|
||||
Math.pow(2, zoomLevel) - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a tile X number at a certain zoom level to a longitude
|
||||
* coordinate.
|
||||
*
|
||||
* @param tileX
|
||||
* the tile X number that should be converted.
|
||||
* @param zoomLevel
|
||||
* the zoom level at which the number should be converted.
|
||||
* @return the longitude value of the tile X number.
|
||||
*/
|
||||
public static double tileXToLongitude(long tileX, int zoomLevel) {
|
||||
return pixelXToLongitude(tileX * Tile.TILE_SIZE, zoomLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a tile Y number at a certain zoom level to a latitude
|
||||
* coordinate.
|
||||
*
|
||||
* @param tileY
|
||||
* the tile Y number that should be converted.
|
||||
* @param zoomLevel
|
||||
* the zoom level at which the number should be converted.
|
||||
* @return the latitude value of the tile Y number.
|
||||
*/
|
||||
public static double tileYToLatitude(long tileY, int zoomLevel) {
|
||||
return pixelYToLatitude(tileY * Tile.TILE_SIZE, zoomLevel);
|
||||
public static double latitudeToPixelY(double latitude, int zoomLevel) {
|
||||
double sinLatitude = Math.sin(latitude * (Math.PI / 180));
|
||||
return (0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI))
|
||||
* ((long) Tile.TILE_SIZE << zoomLevel);
|
||||
}
|
||||
|
||||
private MercatorProjection() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// public static Point projectPoint(GeoPoint geopoint, int z, Point reuse) {
|
||||
// Point out = reuse == null ? new Point() : reuse;
|
||||
//
|
||||
// out.x = (int) MercatorProjection.longitudeToPixelX(geopoint.getLongitude(), z);
|
||||
// out.y = (int) MercatorProjection.latitudeToPixelY(geopoint.getLatitude(), z);
|
||||
//
|
||||
// return out;
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -41,15 +41,6 @@ public class Tile {
|
||||
*/
|
||||
public final byte zoomLevel;
|
||||
|
||||
/**
|
||||
* the pixel X coordinate of the upper left corner of this tile.
|
||||
*/
|
||||
public final long pixelX;
|
||||
/**
|
||||
* the pixel Y coordinate of the upper left corner of this tile.
|
||||
*/
|
||||
public final long pixelY;
|
||||
|
||||
/**
|
||||
* @param tileX
|
||||
* the X number of the tile.
|
||||
@@ -61,8 +52,6 @@ public class Tile {
|
||||
public Tile(int tileX, int tileY, byte zoomLevel) {
|
||||
this.tileX = tileX;
|
||||
this.tileY = tileY;
|
||||
this.pixelX = this.tileX * TILE_SIZE;
|
||||
this.pixelY = this.tileY * TILE_SIZE;
|
||||
this.zoomLevel = zoomLevel;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user