-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:
parent
a6a729244f
commit
8e01dce85e
@ -15,78 +15,73 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.core;
|
package org.oscim.core;
|
||||||
|
|
||||||
|
import org.oscim.utils.FastMath;
|
||||||
|
|
||||||
/** A MapPosition Container. */
|
/** A MapPosition Container. */
|
||||||
public class MapPosition {
|
public class MapPosition {
|
||||||
|
public final static int MAX_ZOOMLEVEL = 20;
|
||||||
|
public final static int MIN_ZOOMLEVEL = 2;
|
||||||
|
|
||||||
public double lon;
|
/** projected position x 0..1 */
|
||||||
public double lat;
|
public double x;
|
||||||
|
/** projected position y 0..1 */
|
||||||
|
public double y;
|
||||||
|
/** absolute scale */
|
||||||
|
public double scale;
|
||||||
|
|
||||||
public double absX;
|
/** rotation angle */
|
||||||
public double absY;
|
|
||||||
public double absScale;
|
|
||||||
|
|
||||||
public float scale;
|
|
||||||
public float angle;
|
public float angle;
|
||||||
|
/** perspective tile */
|
||||||
public float tilt;
|
public float tilt;
|
||||||
|
|
||||||
// map center in tile coordinates of current zoom-level
|
// to be removed
|
||||||
public double x;
|
// FastMath.log2((int) scale)
|
||||||
public double y;
|
|
||||||
public int zoomLevel;
|
public int zoomLevel;
|
||||||
|
|
||||||
public MapPosition() {
|
public MapPosition() {
|
||||||
this.zoomLevel = (byte) 1;
|
|
||||||
this.scale = 1;
|
this.scale = 1;
|
||||||
this.lat = 0;
|
this.x = 0.5;
|
||||||
this.lon = 0;
|
this.y = 0.5;
|
||||||
|
this.zoomLevel = 1;
|
||||||
this.angle = 0;
|
this.angle = 0;
|
||||||
this.x = MercatorProjection.longitudeToPixelX(this.lon, zoomLevel);
|
|
||||||
this.y = MercatorProjection.latitudeToPixelY(this.lat, zoomLevel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void setZoomLevel(int zoomLevel) {
|
||||||
* @param geoPoint
|
|
||||||
* the map position.
|
|
||||||
* @param zoomLevel
|
|
||||||
* the zoom level.
|
|
||||||
* @param scale
|
|
||||||
* ...
|
|
||||||
*/
|
|
||||||
public MapPosition(GeoPoint geoPoint, byte zoomLevel, float scale) {
|
|
||||||
this.zoomLevel = zoomLevel;
|
this.zoomLevel = zoomLevel;
|
||||||
this.scale = scale;
|
this.scale = 1 << zoomLevel;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MapPosition(double latitude, double longitude, int zoomLevel, float scale,
|
public void setScale(double scale) {
|
||||||
float angle) {
|
this.zoomLevel = FastMath.log2((int) scale);
|
||||||
this.zoomLevel = zoomLevel;
|
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
this.lat = latitude;
|
}
|
||||||
this.lon = longitude;
|
|
||||||
this.angle = angle;
|
public void setPosition(GeoPoint geoPoint){
|
||||||
this.x = MercatorProjection.longitudeToPixelX(longitude, zoomLevel);
|
setPosition(geoPoint.getLatitude(), geoPoint.getLongitude());
|
||||||
this.y = MercatorProjection.latitudeToPixelY(latitude, zoomLevel);
|
}
|
||||||
|
|
||||||
|
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) {
|
public void copy(MapPosition other) {
|
||||||
this.zoomLevel = other.zoomLevel;
|
this.zoomLevel = other.zoomLevel;
|
||||||
this.scale = other.scale;
|
|
||||||
this.lat = other.lat;
|
|
||||||
this.lon = other.lon;
|
|
||||||
this.angle = other.angle;
|
this.angle = other.angle;
|
||||||
|
this.scale = other.scale;
|
||||||
this.x = other.x;
|
this.x = other.x;
|
||||||
this.y = other.y;
|
this.y = other.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFromLatLon(double latitude, double longitude, int zoomLevel){
|
public double getZoomScale() {
|
||||||
this.zoomLevel = zoomLevel;
|
return scale / (1 << zoomLevel);
|
||||||
this.x = MercatorProjection.longitudeToPixelX(longitude, zoomLevel);
|
}
|
||||||
this.y = MercatorProjection.latitudeToPixelY(latitude, zoomLevel);
|
|
||||||
|
public GeoPoint getGeoPoint() {
|
||||||
|
return new GeoPoint(MercatorProjection.toLatitude(y),
|
||||||
|
MercatorProjection.toLongitude(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -94,11 +89,11 @@ public class MapPosition {
|
|||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("MapPosition [");
|
builder.append("MapPosition [");
|
||||||
builder.append("lat=");
|
builder.append("lat=");
|
||||||
builder.append(this.lat);
|
builder.append(MercatorProjection.toLatitude(y));
|
||||||
builder.append(", lon=");
|
builder.append(", lon=");
|
||||||
builder.append(this.lon);
|
builder.append(MercatorProjection.toLongitude(x));
|
||||||
builder.append(", zoomLevel=");
|
builder.append(", zoomLevel=");
|
||||||
builder.append(this.zoomLevel);
|
builder.append(zoomLevel);
|
||||||
builder.append("]");
|
builder.append("]");
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.core;
|
package org.oscim.core;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of the spherical Mercator projection.
|
* An implementation of the spherical Mercator projection.
|
||||||
*/
|
*/
|
||||||
@ -61,28 +60,6 @@ public final class MercatorProjection {
|
|||||||
/ ((long) Tile.TILE_SIZE << zoomLevel);
|
/ ((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]
|
* 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);
|
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
|
* Projects a longitude coordinate (in degrees) to the range [0.0,1.0]
|
||||||
* certain zoom level.
|
|
||||||
*
|
*
|
||||||
* @param latitude
|
* @param longitude
|
||||||
* the latitude coordinate that should be converted.
|
* the longitude coordinate that should be converted.
|
||||||
* @param zoomLevel
|
* @return the position .
|
||||||
* the zoom level at which the coordinate should be converted.
|
|
||||||
* @return the tile Y number of the latitude value.
|
|
||||||
*/
|
*/
|
||||||
public static long latitudeToTileY(double latitude, int zoomLevel) {
|
public static double longitudeToX(double longitude) {
|
||||||
return pixelYToTileY(latitudeToPixelY(latitude, zoomLevel), zoomLevel);
|
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 Math.max(Math.min(longitude - 360, LONGITUDE_MAX), LONGITUDE_MIN);
|
||||||
|
|
||||||
return longitude;
|
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);
|
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
|
* @param longitude
|
||||||
* the pixel X coordinate that should be converted.
|
* the longitude coordinate that should be converted.
|
||||||
* @param zoomLevel
|
* @param zoomLevel
|
||||||
* the zoom level at which the coordinate should be converted.
|
* 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) {
|
public static double longitudeToPixelX(double longitude, int zoomLevel) {
|
||||||
return (int) Math.min(Math.max(pixelX / Tile.TILE_SIZE, 0),
|
return (longitude + 180) / 360 * ((long) Tile.TILE_SIZE << zoomLevel);
|
||||||
Math.pow(2, zoomLevel) - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -232,69 +162,22 @@ public final class MercatorProjection {
|
|||||||
return 90 - 360 * Math.atan(Math.exp(-y * (2 * Math.PI))) / Math.PI;
|
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
|
* @param latitude
|
||||||
* the pixel Y coordinate that should be converted.
|
* the latitude coordinate that should be converted.
|
||||||
* @param zoomLevel
|
* @param zoomLevel
|
||||||
* the zoom level at which the coordinate should be converted.
|
* 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) {
|
public static double latitudeToPixelY(double latitude, int zoomLevel) {
|
||||||
return (int) Math.min(Math.max(pixelY / Tile.TILE_SIZE, 0),
|
double sinLatitude = Math.sin(latitude * (Math.PI / 180));
|
||||||
Math.pow(2, zoomLevel) - 1);
|
return (0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI))
|
||||||
}
|
* ((long) Tile.TILE_SIZE << zoomLevel);
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private MercatorProjection() {
|
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;
|
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
|
* @param tileX
|
||||||
* the X number of the tile.
|
* the X number of the tile.
|
||||||
@ -61,8 +52,6 @@ public class Tile {
|
|||||||
public Tile(int tileX, int tileY, byte zoomLevel) {
|
public Tile(int tileX, int tileY, byte zoomLevel) {
|
||||||
this.tileX = tileX;
|
this.tileX = tileX;
|
||||||
this.tileY = tileY;
|
this.tileY = tileY;
|
||||||
this.pixelX = this.tileX * TILE_SIZE;
|
|
||||||
this.pixelY = this.tileY * TILE_SIZE;
|
|
||||||
this.zoomLevel = zoomLevel;
|
this.zoomLevel = zoomLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,6 @@ import java.io.IOException;
|
|||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
|
|
||||||
import org.oscim.core.GeometryBuffer;
|
import org.oscim.core.GeometryBuffer;
|
||||||
import org.oscim.core.MercatorProjection;
|
|
||||||
import org.oscim.core.Tag;
|
import org.oscim.core.Tag;
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.database.IMapDatabase;
|
import org.oscim.database.IMapDatabase;
|
||||||
@ -443,6 +442,8 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void processBlocks(IMapDatabaseCallback mapDatabaseCallback,
|
private void processBlocks(IMapDatabaseCallback mapDatabaseCallback,
|
||||||
QueryParameters queryParameters,
|
QueryParameters queryParameters,
|
||||||
SubFileParameter subFileParameter) throws IOException {
|
SubFileParameter subFileParameter) throws IOException {
|
||||||
@ -527,10 +528,10 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// calculate the top-left coordinates of the underlying tile
|
// calculate the top-left coordinates of the underlying tile
|
||||||
double tileLatitudeDeg = MercatorProjection.tileYToLatitude(
|
double tileLatitudeDeg = Projection.tileYToLatitude(
|
||||||
subFileParameter.boundaryTileTop + row,
|
subFileParameter.boundaryTileTop + row,
|
||||||
subFileParameter.baseZoomLevel);
|
subFileParameter.baseZoomLevel);
|
||||||
double tileLongitudeDeg = MercatorProjection.tileXToLongitude(
|
double tileLongitudeDeg = Projection.tileXToLongitude(
|
||||||
subFileParameter.boundaryTileLeft
|
subFileParameter.boundaryTileLeft
|
||||||
+ column, subFileParameter.baseZoomLevel);
|
+ column, subFileParameter.baseZoomLevel);
|
||||||
mTileLatitude = (int) (tileLatitudeDeg * 1000000);
|
mTileLatitude = (int) (tileLatitudeDeg * 1000000);
|
||||||
@ -590,9 +591,8 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
Tag[] tags = null;
|
Tag[] tags = null;
|
||||||
Tag[] curTags;
|
Tag[] curTags;
|
||||||
|
|
||||||
|
long x = mTile.tileX * Tile.TILE_SIZE;
|
||||||
long x = mTile.pixelX;
|
long y = mTile.tileY * Tile.TILE_SIZE + Tile.TILE_SIZE;
|
||||||
long y = mTile.pixelY + Tile.TILE_SIZE;
|
|
||||||
long z = Tile.TILE_SIZE << mTile.zoomLevel;
|
long z = Tile.TILE_SIZE << mTile.zoomLevel;
|
||||||
|
|
||||||
long dx = (x - (z >> 1));
|
long dx = (x - (z >> 1));
|
||||||
@ -917,7 +917,7 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
int add = (hasName ? 1 : 0) + (hasHouseNr ? 1 : 0) + (hasRef ? 1 : 0);
|
int add = (hasName ? 1 : 0) + (hasHouseNr ? 1 : 0) + (hasRef ? 1 : 0);
|
||||||
int addTag = tags.length;
|
int addTag = tags.length;
|
||||||
|
|
||||||
if (add > 0){
|
if (add > 0) {
|
||||||
curTags = new Tag[tags.length + add];
|
curTags = new Tag[tags.length + add];
|
||||||
System.arraycopy(tags, 0, curTags, 0, tags.length);
|
System.arraycopy(tags, 0, curTags, 0, tags.length);
|
||||||
}
|
}
|
||||||
@ -1055,8 +1055,8 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
|
|
||||||
private boolean projectToTile(float[] coords, short[] indices) {
|
private boolean projectToTile(float[] coords, short[] indices) {
|
||||||
|
|
||||||
long x = mTile.pixelX;
|
long x = mTile.tileX * Tile.TILE_SIZE;
|
||||||
long y = mTile.pixelY + Tile.TILE_SIZE;
|
long y = mTile.tileY * Tile.TILE_SIZE + Tile.TILE_SIZE;
|
||||||
long z = Tile.TILE_SIZE << mTile.zoomLevel;
|
long z = Tile.TILE_SIZE << mTile.zoomLevel;
|
||||||
|
|
||||||
double divx, divy = 0;
|
double divx, divy = 0;
|
||||||
|
|||||||
108
src/org/oscim/database/mapfile/Projection.java
Normal file
108
src/org/oscim/database/mapfile/Projection.java
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.oscim.database.mapfile;
|
||||||
|
|
||||||
|
import org.oscim.core.MercatorProjection;
|
||||||
|
import org.oscim.core.Tile;
|
||||||
|
|
||||||
|
public class Projection {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 MercatorProjection.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 MercatorProjection.pixelYToLatitude(tileY * Tile.TILE_SIZE, zoomLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a latitude coordinate (in degrees) to a tile Y number 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 tile Y number of the latitude value.
|
||||||
|
*/
|
||||||
|
public static long latitudeToTileY(double latitude, int zoomLevel) {
|
||||||
|
return pixelYToTileY(MercatorProjection.latitudeToPixelY(latitude, zoomLevel), zoomLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(MercatorProjection.longitudeToPixelX(longitude, zoomLevel), zoomLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a pixel X coordinate to the tile X number.
|
||||||
|
*
|
||||||
|
* @param pixelX
|
||||||
|
* the pixel X coordinate that should be converted.
|
||||||
|
* @param zoomLevel
|
||||||
|
* the zoom level at which the coordinate should be converted.
|
||||||
|
* @return the tile X number.
|
||||||
|
*/
|
||||||
|
public static int pixelXToTileX(double pixelX, int zoomLevel) {
|
||||||
|
return (int) Math.min(Math.max(pixelX / Tile.TILE_SIZE, 0),
|
||||||
|
Math.pow(2, zoomLevel) - 1);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Converts a pixel Y coordinate to the tile Y number.
|
||||||
|
*
|
||||||
|
* @param pixelY
|
||||||
|
* the pixel Y coordinate that should be converted.
|
||||||
|
* @param zoomLevel
|
||||||
|
* the zoom level at which the coordinate should be converted.
|
||||||
|
* @return the tile Y number.
|
||||||
|
*/
|
||||||
|
public static int pixelYToTileY(double pixelY, int zoomLevel) {
|
||||||
|
return (int) Math.min(Math.max(pixelY / Tile.TILE_SIZE, 0),
|
||||||
|
Math.pow(2, zoomLevel) - 1);
|
||||||
|
}
|
||||||
|
private Projection(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.database.mapfile.header;
|
package org.oscim.database.mapfile.header;
|
||||||
|
|
||||||
import org.oscim.core.MercatorProjection;
|
import org.oscim.database.mapfile.Projection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds all parameters of a sub-file.
|
* Holds all parameters of a sub-file.
|
||||||
@ -110,6 +110,7 @@ public class SubFileParameter {
|
|||||||
*/
|
*/
|
||||||
private final int hashCodeValue;
|
private final int hashCodeValue;
|
||||||
|
|
||||||
|
|
||||||
SubFileParameter(SubFileParameterBuilder subFileParameterBuilder) {
|
SubFileParameter(SubFileParameterBuilder subFileParameterBuilder) {
|
||||||
this.startAddress = subFileParameterBuilder.startAddress;
|
this.startAddress = subFileParameterBuilder.startAddress;
|
||||||
this.indexStartAddress = subFileParameterBuilder.indexStartAddress;
|
this.indexStartAddress = subFileParameterBuilder.indexStartAddress;
|
||||||
@ -120,16 +121,16 @@ public class SubFileParameter {
|
|||||||
this.hashCodeValue = calculateHashCode();
|
this.hashCodeValue = calculateHashCode();
|
||||||
|
|
||||||
// calculate the XY numbers of the boundary tiles in this sub-file
|
// calculate the XY numbers of the boundary tiles in this sub-file
|
||||||
this.boundaryTileBottom = MercatorProjection.latitudeToTileY(
|
this.boundaryTileBottom = Projection.latitudeToTileY(
|
||||||
subFileParameterBuilder.boundingBox.minLatitudeE6
|
subFileParameterBuilder.boundingBox.minLatitudeE6
|
||||||
/ COORDINATES_DIVISOR, this.baseZoomLevel);
|
/ COORDINATES_DIVISOR, this.baseZoomLevel);
|
||||||
this.boundaryTileLeft = MercatorProjection.longitudeToTileX(
|
this.boundaryTileLeft = Projection.longitudeToTileX(
|
||||||
subFileParameterBuilder.boundingBox.minLongitudeE6
|
subFileParameterBuilder.boundingBox.minLongitudeE6
|
||||||
/ COORDINATES_DIVISOR, this.baseZoomLevel);
|
/ COORDINATES_DIVISOR, this.baseZoomLevel);
|
||||||
this.boundaryTileTop = MercatorProjection.latitudeToTileY(
|
this.boundaryTileTop = Projection.latitudeToTileY(
|
||||||
subFileParameterBuilder.boundingBox.maxLatitudeE6
|
subFileParameterBuilder.boundingBox.maxLatitudeE6
|
||||||
/ COORDINATES_DIVISOR, this.baseZoomLevel);
|
/ COORDINATES_DIVISOR, this.baseZoomLevel);
|
||||||
this.boundaryTileRight = MercatorProjection.longitudeToTileX(
|
this.boundaryTileRight = Projection.longitudeToTileX(
|
||||||
subFileParameterBuilder.boundingBox.maxLongitudeE6
|
subFileParameterBuilder.boundingBox.maxLongitudeE6
|
||||||
/ COORDINATES_DIVISOR, this.baseZoomLevel);
|
/ COORDINATES_DIVISOR, this.baseZoomLevel);
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,6 @@ import org.oscim.theme.renderinstruction.RenderInstruction;
|
|||||||
import org.oscim.theme.renderinstruction.Text;
|
import org.oscim.theme.renderinstruction.Text;
|
||||||
import org.oscim.utils.LineClipper;
|
import org.oscim.utils.LineClipper;
|
||||||
import org.oscim.view.DebugSettings;
|
import org.oscim.view.DebugSettings;
|
||||||
import org.oscim.view.MapView;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
@ -80,7 +79,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
new float[] { 0, 0, 0, Tile.TILE_SIZE,
|
new float[] { 0, 0, 0, Tile.TILE_SIZE,
|
||||||
Tile.TILE_SIZE, Tile.TILE_SIZE,
|
Tile.TILE_SIZE, Tile.TILE_SIZE,
|
||||||
Tile.TILE_SIZE, 0, 0, 0 },
|
Tile.TILE_SIZE, 0, 0, 0 },
|
||||||
new short[1]),
|
new short[] {10}),
|
||||||
new Tag[] { new Tag("debug", "box") }
|
new Tag[] { new Tag("debug", "box") }
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -151,16 +150,14 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
setScaleStrokeWidth(mTile.zoomLevel);
|
setScaleStrokeWidth(mTile.zoomLevel);
|
||||||
|
|
||||||
// account for area changes with latitude
|
// account for area changes with latitude
|
||||||
double latitude = MercatorProjection.pixelYToLatitude(mTile.pixelY + (Tile.TILE_SIZE >> 1),
|
double latitude = MercatorProjection.toLatitude(mTile.y);
|
||||||
mTile.zoomLevel);
|
|
||||||
mLatScaleFactor = 0.5f + 0.5f * ((float) Math.sin(Math.abs(latitude) * (Math.PI / 180)));
|
mLatScaleFactor = 0.5f + 0.5f * ((float) Math.sin(Math.abs(latitude) * (Math.PI / 180)));
|
||||||
|
|
||||||
mGroundResolution = (float) (Math.cos(latitude * (Math.PI / 180))
|
mGroundResolution = (float) (Math.cos(latitude * (Math.PI / 180))
|
||||||
* MercatorProjection.EARTH_CIRCUMFERENCE
|
* MercatorProjection.EARTH_CIRCUMFERENCE
|
||||||
/ ((long) Tile.TILE_SIZE << mTile.zoomLevel));
|
/ ((long) Tile.TILE_SIZE << mTile.zoomLevel));
|
||||||
|
|
||||||
Log.d(TAG, mTile + " " + mGroundResolution);
|
|
||||||
|
|
||||||
mTile.layers = new Layers();
|
mTile.layers = new Layers();
|
||||||
|
|
||||||
// query database, which calls renderWay and renderPOI
|
// query database, which calls renderWay and renderPOI
|
||||||
@ -188,7 +185,6 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
|
|
||||||
// draw tile box
|
// draw tile box
|
||||||
mWay = mDebugWay;
|
mWay = mDebugWay;
|
||||||
mWay.geom.index[0] = (short) (MapView.enableClosePolygons ? 8 : 10);
|
|
||||||
mDrawingLayer = 100 * renderLevels;
|
mDrawingLayer = 100 * renderLevels;
|
||||||
ri = renderTheme.matchWay(mDebugWay.tags, (byte) 0, false);
|
ri = renderTheme.matchWay(mDebugWay.tags, (byte) 0, false);
|
||||||
renderWay(ri, mDebugWay.tags);
|
renderWay(ri, mDebugWay.tags);
|
||||||
|
|||||||
@ -41,6 +41,8 @@ public class BuildingOverlay extends Overlay {
|
|||||||
private final float mFadeTime = 300;
|
private final float mFadeTime = 300;
|
||||||
private float mAlpha = 1;
|
private float mAlpha = 1;
|
||||||
|
|
||||||
|
private final static int MIN_ZOOM = 17;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent e) {
|
public boolean onTouchEvent(MotionEvent e) {
|
||||||
int action = e.getAction() & MotionEvent.ACTION_MASK;
|
int action = e.getAction() & MotionEvent.ACTION_MASK;
|
||||||
@ -48,7 +50,7 @@ public class BuildingOverlay extends Overlay {
|
|||||||
multi++;
|
multi++;
|
||||||
} else if (action == MotionEvent.ACTION_POINTER_UP) {
|
} else if (action == MotionEvent.ACTION_POINTER_UP) {
|
||||||
multi--;
|
multi--;
|
||||||
if (mPrevZoom != 17 && mAlpha > 0) {
|
if (!mActive && mAlpha > 0) {
|
||||||
// finish hiding
|
// finish hiding
|
||||||
//Log.d(TAG, "add multi hide timer " + mAlpha);
|
//Log.d(TAG, "add multi hide timer " + mAlpha);
|
||||||
addShowTimer(mFadeTime * mAlpha, false);
|
addShowTimer(mFadeTime * mAlpha, false);
|
||||||
@ -65,19 +67,20 @@ public class BuildingOverlay extends Overlay {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int mPrevZoom = 0;
|
private boolean mActive = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdate(MapPosition mapPosition, boolean changed) {
|
public void onUpdate(MapPosition mapPosition, boolean changed) {
|
||||||
int z = mapPosition.zoomLevel;
|
boolean show = mapPosition.scale >= (1 << MIN_ZOOM);
|
||||||
if (z == mPrevZoom)
|
|
||||||
|
if (show && mActive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (z == 17) {
|
if (show) {
|
||||||
// start showing
|
// start showing
|
||||||
//Log.d(TAG, "add show timer " + mAlpha);
|
//Log.d(TAG, "add show timer " + mAlpha);
|
||||||
addShowTimer(mFadeTime * (1 - mAlpha), true);
|
addShowTimer(mFadeTime * (1 - mAlpha), true);
|
||||||
} else if (mPrevZoom == 17) {
|
} else if (mActive) {
|
||||||
// indicate hiding
|
// indicate hiding
|
||||||
if (multi > 0) {
|
if (multi > 0) {
|
||||||
//Log.d(TAG, "add fade timer " + mAlpha);
|
//Log.d(TAG, "add fade timer " + mAlpha);
|
||||||
@ -87,8 +90,7 @@ public class BuildingOverlay extends Overlay {
|
|||||||
addShowTimer(mFadeTime * mAlpha, false);
|
addShowTimer(mFadeTime * mAlpha, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mActive = show;
|
||||||
mPrevZoom = z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fade(float duration, long tick, boolean dir, float max) {
|
void fade(float duration, long tick, boolean dir, float max) {
|
||||||
|
|||||||
@ -24,10 +24,12 @@ package org.oscim.overlay;
|
|||||||
import org.oscim.core.GeoPoint;
|
import org.oscim.core.GeoPoint;
|
||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.core.MercatorProjection;
|
import org.oscim.core.MercatorProjection;
|
||||||
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.overlay.OverlayItem.HotspotPlace;
|
import org.oscim.overlay.OverlayItem.HotspotPlace;
|
||||||
import org.oscim.renderer.GLRenderer.Matrices;
|
import org.oscim.renderer.GLRenderer.Matrices;
|
||||||
import org.oscim.renderer.layer.SymbolLayer;
|
import org.oscim.renderer.layer.SymbolLayer;
|
||||||
import org.oscim.renderer.overlays.BasicOverlay;
|
import org.oscim.renderer.overlays.BasicOverlay;
|
||||||
|
import org.oscim.utils.FastMath;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
@ -71,8 +73,8 @@ public abstract class ItemizedOverlay<Item extends OverlayItem> extends Overlay
|
|||||||
|
|
||||||
private int mSize;
|
private int mSize;
|
||||||
|
|
||||||
// pre-projected points to zoomlovel 20
|
// pre-projected points to zoomlovel 18
|
||||||
private static final byte MAX_ZOOM = 20;
|
private static final byte MAX_ZOOM = 18;
|
||||||
|
|
||||||
class ItemOverlay extends BasicOverlay {
|
class ItemOverlay extends BasicOverlay {
|
||||||
|
|
||||||
@ -95,9 +97,16 @@ public abstract class ItemizedOverlay<Item extends OverlayItem> extends Overlay
|
|||||||
|
|
||||||
mUpdate = false;
|
mUpdate = false;
|
||||||
|
|
||||||
int diff = MAX_ZOOM - curPos.zoomLevel;
|
//int mx = (int) curPos.x;
|
||||||
int mx = (int) curPos.x;
|
//int my = (int) curPos.y;
|
||||||
int my = (int) curPos.y;
|
|
||||||
|
//int z = curPos.zoomLevel;
|
||||||
|
|
||||||
|
int z = FastMath.log2((int) curPos.scale);
|
||||||
|
int diff = MAX_ZOOM - z;
|
||||||
|
|
||||||
|
int mx = (int) (curPos.x * (Tile.TILE_SIZE << z));
|
||||||
|
int my = (int) (curPos.y * (Tile.TILE_SIZE << z));
|
||||||
|
|
||||||
// limit could be 1 if we update on every position change
|
// limit could be 1 if we update on every position change
|
||||||
float limit = 1.5f;
|
float limit = 1.5f;
|
||||||
@ -122,6 +131,8 @@ public abstract class ItemizedOverlay<Item extends OverlayItem> extends Overlay
|
|||||||
for (InternalItem it = mItems; it != null; it = it.next) {
|
for (InternalItem it = mItems; it != null; it = it.next) {
|
||||||
it.x = (it.px >> diff) - mx;
|
it.x = (it.px >> diff) - mx;
|
||||||
it.y = (it.py >> diff) - my;
|
it.y = (it.py >> diff) - my;
|
||||||
|
//it.x = it.px - mx;
|
||||||
|
//it.y = it.py - my;
|
||||||
|
|
||||||
if (it.x > max || it.x < -max || it.y > max || it.y < -max) {
|
if (it.x > max || it.x < -max || it.y > max || it.y < -max) {
|
||||||
if (it.visible) {
|
if (it.visible) {
|
||||||
@ -159,21 +170,22 @@ public abstract class ItemizedOverlay<Item extends OverlayItem> extends Overlay
|
|||||||
|
|
||||||
// only update when zoomlevel changed, new items are visible
|
// only update when zoomlevel changed, new items are visible
|
||||||
// or more than 10 of the current items became invisible
|
// or more than 10 of the current items became invisible
|
||||||
if (((curPos.zoomLevel == mMapPosition.zoomLevel || numVisible == 0)) &&
|
if ((numVisible == 0) && (changedVisible == 0 && changesInvisible < 10))
|
||||||
(changedVisible == 0 && changesInvisible < 10))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// keep position for current state
|
// keep position for current state
|
||||||
// updateMapPosition();
|
// updateMapPosition();
|
||||||
// TODO add copy utility function
|
mMapPosition.copy(curPos);
|
||||||
mMapPosition.x = curPos.x;
|
|
||||||
mMapPosition.y = curPos.y;
|
//mMapPosition.x = curPos.x;
|
||||||
mMapPosition.zoomLevel = curPos.zoomLevel;
|
//mMapPosition.y = curPos.y;
|
||||||
mMapPosition.scale = curPos.scale;
|
//mMapPosition.zoomLevel = curPos.zoomLevel;
|
||||||
mMapPosition.angle = curPos.angle;
|
//mMapPosition.scale = curPos.scale;
|
||||||
|
//mMapPosition.angle = curPos.angle;
|
||||||
|
|
||||||
// items are placed relative to scale == 1
|
// items are placed relative to scale == 1
|
||||||
mMapPosition.scale = 1;
|
// mMapPosition.scale = 1;
|
||||||
|
mMapPosition.scale = 1 << z;
|
||||||
|
|
||||||
layers.clear();
|
layers.clear();
|
||||||
|
|
||||||
@ -423,7 +435,7 @@ public abstract class ItemizedOverlay<Item extends OverlayItem> extends Overlay
|
|||||||
return marker;
|
return marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Drawable makeMarker(Resources res, int id, HotspotPlace place){
|
public static Drawable makeMarker(Resources res, int id, HotspotPlace place) {
|
||||||
Drawable marker = res.getDrawable(id);
|
Drawable marker = res.getDrawable(id);
|
||||||
if (place == null)
|
if (place == null)
|
||||||
boundToHotspot(marker, HotspotPlace.CENTER);
|
boundToHotspot(marker, HotspotPlace.CENTER);
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import java.util.List;
|
|||||||
import org.oscim.core.GeoPoint;
|
import org.oscim.core.GeoPoint;
|
||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.core.MercatorProjection;
|
import org.oscim.core.MercatorProjection;
|
||||||
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.renderer.GLRenderer.Matrices;
|
import org.oscim.renderer.GLRenderer.Matrices;
|
||||||
import org.oscim.renderer.layer.Layer;
|
import org.oscim.renderer.layer.Layer;
|
||||||
import org.oscim.renderer.layer.LineLayer;
|
import org.oscim.renderer.layer.LineLayer;
|
||||||
@ -108,12 +109,6 @@ public class PathOverlay extends Overlay {
|
|||||||
|
|
||||||
int size = mSize;
|
int size = mSize;
|
||||||
|
|
||||||
// keep position to render relative to current state
|
|
||||||
mMapPosition.copy(curPos);
|
|
||||||
|
|
||||||
// items are placed relative to scale == 1
|
|
||||||
mMapPosition.scale = 1;
|
|
||||||
|
|
||||||
// layers.clear();
|
// layers.clear();
|
||||||
LineLayer ll = (LineLayer) layers.getLayer(1, Layer.LINE);
|
LineLayer ll = (LineLayer) layers.getLayer(1, Layer.LINE);
|
||||||
// reset verticesCnt to reuse layer
|
// reset verticesCnt to reuse layer
|
||||||
@ -124,15 +119,22 @@ public class PathOverlay extends Overlay {
|
|||||||
int x, y, px = 0, py = 0;
|
int x, y, px = 0, py = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
int diff = MAX_ZOOM - mMapPosition.zoomLevel;
|
//int mx = (int) mMapPosition.x;
|
||||||
int mx = (int) mMapPosition.x;
|
//int my = (int) mMapPosition.y;
|
||||||
int my = (int) mMapPosition.y;
|
//int z = curPos.zoomLevel;
|
||||||
|
int z = FastMath.log2((int) curPos.scale);
|
||||||
|
int diff = MAX_ZOOM - z;
|
||||||
|
int mx = (int) (curPos.x * (Tile.TILE_SIZE << z));
|
||||||
|
int my = (int) (curPos.y * (Tile.TILE_SIZE << z));
|
||||||
|
|
||||||
for (int j = 0; j < size; j += 2) {
|
for (int j = 0; j < size; j += 2) {
|
||||||
// TODO translate mapPosition and do this after clipping
|
// TODO translate mapPosition and do this after clipping
|
||||||
x = (mPreprojected[j + 0] >> diff) - mx;
|
x = (mPreprojected[j + 0] >> diff) - mx;
|
||||||
y = (mPreprojected[j + 1] >> diff) - my;
|
y = (mPreprojected[j + 1] >> diff) - my;
|
||||||
|
|
||||||
|
//x = (mPreprojected[j + 0]) - mx;
|
||||||
|
//y = (mPreprojected[j + 1]) - my;
|
||||||
|
|
||||||
// TODO use line clipping, this doesnt work with 'GreatCircle'
|
// TODO use line clipping, this doesnt work with 'GreatCircle'
|
||||||
// TODO clip to view bounding box
|
// TODO clip to view bounding box
|
||||||
if (x > max || x < -max || y > max || y < -max) {
|
if (x > max || x < -max || y > max || y < -max) {
|
||||||
@ -157,6 +159,12 @@ public class PathOverlay extends Overlay {
|
|||||||
mIndex[0] = (short) i;
|
mIndex[0] = (short) i;
|
||||||
ll.addLine(projected, mIndex, false);
|
ll.addLine(projected, mIndex, false);
|
||||||
|
|
||||||
|
// keep position to render relative to current state
|
||||||
|
mMapPosition.copy(curPos);
|
||||||
|
|
||||||
|
// items are placed relative to scale 1
|
||||||
|
mMapPosition.scale = 1 << z;
|
||||||
|
|
||||||
newData = true;
|
newData = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,6 @@ import org.oscim.core.Tile;
|
|||||||
import org.oscim.renderer.layer.Layers;
|
import org.oscim.renderer.layer.Layers;
|
||||||
import org.oscim.renderer.overlays.RenderOverlay;
|
import org.oscim.renderer.overlays.RenderOverlay;
|
||||||
import org.oscim.theme.RenderTheme;
|
import org.oscim.theme.RenderTheme;
|
||||||
import org.oscim.utils.FastMath;
|
|
||||||
import org.oscim.utils.GlUtils;
|
import org.oscim.utils.GlUtils;
|
||||||
import org.oscim.utils.Matrix4;
|
import org.oscim.utils.Matrix4;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
@ -317,31 +316,21 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
for (int i = 0; i < mDrawTiles.cnt; i++)
|
for (int i = 0; i < mDrawTiles.cnt; i++)
|
||||||
tiles[i].isVisible = false;
|
tiles[i].isVisible = false;
|
||||||
|
|
||||||
// relative zoom-level, 'tiles' could not have been updated after
|
int z = tiles[0].zoomLevel;
|
||||||
// zoom-level changed.
|
|
||||||
float div = FastMath.pow(pos.zoomLevel - tiles[0].zoomLevel);
|
|
||||||
|
|
||||||
// draw additional tiles on max zoom-level:
|
double curScale = Tile.TILE_SIZE * pos.scale;
|
||||||
// to make sure buildings that are half visible but
|
double tileScale = Tile.TILE_SIZE * (pos.scale / (1 << z));
|
||||||
// the not ground tile are still drawn.
|
|
||||||
float scale = pos.scale;
|
|
||||||
if (scale > 2)
|
|
||||||
scale = 2;
|
|
||||||
|
|
||||||
// transform screen coordinates to tile coordinates
|
|
||||||
float tileScale = scale * div * Tile.TILE_SIZE;
|
|
||||||
double px = pos.x * scale;
|
|
||||||
double py = pos.y * scale;
|
|
||||||
for (int i = 0; i < 8; i += 2) {
|
for (int i = 0; i < 8; i += 2) {
|
||||||
coords[i + 0] = (float) (px + coords[i + 0]) / tileScale;
|
coords[i + 0] = (float) ((pos.x * curScale + coords[i + 0]) / tileScale);
|
||||||
coords[i + 1] = (float) (py + coords[i + 1]) / tileScale;
|
coords[i + 1] = (float) ((pos.y * curScale + coords[i + 1]) / tileScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// count placeholder tiles
|
// count placeholder tiles
|
||||||
mNumTileHolder = 0;
|
mNumTileHolder = 0;
|
||||||
|
|
||||||
// check visibile tiles
|
// check visibile tiles
|
||||||
mScanBox.scan(coords, tiles[0].zoomLevel);
|
mScanBox.scan(coords, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,21 +440,23 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
boolean tilesChanged = false;
|
boolean tilesChanged = false;
|
||||||
|
boolean positionChanged = false;
|
||||||
|
|
||||||
// check if the tiles have changed...
|
// check if the tiles have changed...
|
||||||
if (serial != mDrawTiles.serial) {
|
if (serial != mDrawTiles.serial) {
|
||||||
mMapPosition.zoomLevel = -1;
|
|
||||||
tilesChanged = true;
|
tilesChanged = true;
|
||||||
|
// FIXME needed?
|
||||||
|
positionChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get current MapPosition, set mTileCoords (mapping of screen to model
|
// get current MapPosition, set mTileCoords (mapping of screen to model
|
||||||
// coordinates)
|
// coordinates)
|
||||||
MapPosition pos = mMapPosition;
|
MapPosition pos = mMapPosition;
|
||||||
boolean positionChanged;
|
|
||||||
|
|
||||||
synchronized (mMapViewPosition) {
|
synchronized (mMapViewPosition) {
|
||||||
mMapViewPosition.updateAnimation();
|
mMapViewPosition.updateAnimation();
|
||||||
|
|
||||||
positionChanged = mMapViewPosition.getMapPosition(pos);
|
positionChanged |= mMapViewPosition.getMapPosition(pos);
|
||||||
|
|
||||||
if (positionChanged)
|
if (positionChanged)
|
||||||
mMapViewPosition.getMapViewProjection(mTileCoords);
|
mMapViewPosition.getMapViewProjection(mTileCoords);
|
||||||
|
|||||||
@ -23,7 +23,6 @@ import static android.opengl.GLES20.glUniform1f;
|
|||||||
import static android.opengl.GLES20.glVertexAttribPointer;
|
import static android.opengl.GLES20.glVertexAttribPointer;
|
||||||
|
|
||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.generator.TileGenerator;
|
|
||||||
import org.oscim.renderer.GLRenderer.Matrices;
|
import org.oscim.renderer.GLRenderer.Matrices;
|
||||||
import org.oscim.renderer.layer.Layer;
|
import org.oscim.renderer.layer.Layer;
|
||||||
import org.oscim.renderer.layer.Layers;
|
import org.oscim.renderer.layer.Layers;
|
||||||
@ -130,15 +129,17 @@ public final class LineRenderer {
|
|||||||
//glUniformMatrix4fv(hLineMatrix[mode], 1, false, matrix, 0);
|
//glUniformMatrix4fv(hLineMatrix[mode], 1, false, matrix, 0);
|
||||||
m.mvp.setAsUniform(hLineMatrix[mode]);
|
m.mvp.setAsUniform(hLineMatrix[mode]);
|
||||||
|
|
||||||
|
//int zoom = FastMath.log2((int) pos.absScale);
|
||||||
int zoom = pos.zoomLevel;
|
int zoom = pos.zoomLevel;
|
||||||
float scale = pos.scale;
|
|
||||||
|
double scale = pos.getZoomScale();
|
||||||
|
|
||||||
// Line scale factor for non fixed lines: Within a zoom-
|
// Line scale factor for non fixed lines: Within a zoom-
|
||||||
// level lines would be scaled by the factor 2 by view-matrix.
|
// level lines would be scaled by the factor 2 by view-matrix.
|
||||||
// Though lines should only scale by sqrt(2). This is achieved
|
// Though lines should only scale by sqrt(2). This is achieved
|
||||||
// by inverting scaling of extrusion vector with: width/sqrt(s).
|
// by inverting scaling of extrusion vector with: width/sqrt(s).
|
||||||
// within one zoom-level: 1 <= s <= 2
|
// within one zoom-level: 1 <= s <= 2
|
||||||
float s = scale / div;
|
double s = scale / div;
|
||||||
float lineScale = (float) Math.sqrt(s * 2 / 2.2);
|
float lineScale = (float) Math.sqrt(s * 2 / 2.2);
|
||||||
|
|
||||||
// scale factor to map one pixel on tile to one pixel on screen:
|
// scale factor to map one pixel on tile to one pixel on screen:
|
||||||
@ -146,7 +147,7 @@ public final class LineRenderer {
|
|||||||
float pixel = 0;
|
float pixel = 0;
|
||||||
|
|
||||||
if (mode == 1)
|
if (mode == 1)
|
||||||
pixel = 1.5f / s;
|
pixel = (float) (1.5 / s);
|
||||||
|
|
||||||
glUniform1f(uLineScale, pixel);
|
glUniform1f(uLineScale, pixel);
|
||||||
int lineMode = 0;
|
int lineMode = 0;
|
||||||
@ -154,7 +155,7 @@ public final class LineRenderer {
|
|||||||
|
|
||||||
boolean blur = false;
|
boolean blur = false;
|
||||||
// dont increase scale when max is reached
|
// dont increase scale when max is reached
|
||||||
boolean strokeMaxZoom = zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL;
|
//boolean strokeMaxZoom = zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL;
|
||||||
|
|
||||||
Layer l = curLayer;
|
Layer l = curLayer;
|
||||||
for (; l != null && l.type == Layer.LINE; l = l.next) {
|
for (; l != null && l.type == Layer.LINE; l = l.next) {
|
||||||
@ -167,7 +168,7 @@ public final class LineRenderer {
|
|||||||
} else if (line.fade > zoom) {
|
} else if (line.fade > zoom) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
float alpha = (scale > 1.2f ? scale : 1.2f) - 1f;
|
float alpha = (float) (scale > 1.2 ? scale : 1.2) - 1;
|
||||||
GlUtils.setColor(uLineColor, line.color, alpha);
|
GlUtils.setColor(uLineColor, line.color, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,10 +181,10 @@ public final class LineRenderer {
|
|||||||
// draw linelayers references by this outline
|
// draw linelayers references by this outline
|
||||||
for (LineLayer o = ll.outlines; o != null; o = o.outlines) {
|
for (LineLayer o = ll.outlines; o != null; o = o.outlines) {
|
||||||
|
|
||||||
if (o.line.fixed || strokeMaxZoom) {
|
if (o.line.fixed /* || strokeMaxZoom */) {
|
||||||
width = (ll.width + o.width) / s;
|
width = (float) ((ll.width + o.width) / s);
|
||||||
} else {
|
} else {
|
||||||
width = ll.width / s + o.width / lineScale;
|
width = (float) (ll.width / s + o.width / lineScale);
|
||||||
|
|
||||||
// check min-size for outline
|
// check min-size for outline
|
||||||
if (o.line.min > 0 && o.width * lineScale < o.line.min * 2)
|
if (o.line.min > 0 && o.width * lineScale < o.line.min * 2)
|
||||||
@ -193,7 +194,7 @@ public final class LineRenderer {
|
|||||||
glUniform1f(uLineWidth, width * COORD_SCALE_BY_DIR_SCALE);
|
glUniform1f(uLineWidth, width * COORD_SCALE_BY_DIR_SCALE);
|
||||||
|
|
||||||
if (line.blur != 0) {
|
if (line.blur != 0) {
|
||||||
glUniform1f(uLineScale, 1f - (line.blur / s));
|
glUniform1f(uLineScale, (float) (1 - (line.blur / s)));
|
||||||
blur = true;
|
blur = true;
|
||||||
} else if (mode == 1) {
|
} else if (mode == 1) {
|
||||||
glUniform1f(uLineScale, pixel / width);
|
glUniform1f(uLineScale, pixel / width);
|
||||||
@ -212,10 +213,10 @@ public final class LineRenderer {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (line.fixed || strokeMaxZoom) {
|
if (line.fixed /* || strokeMaxZoom */) {
|
||||||
// invert scaling of extrusion vectors so that line
|
// invert scaling of extrusion vectors so that line
|
||||||
// width stays the same.
|
// width stays the same.
|
||||||
width = ll.width / s;
|
width = (float) (ll.width / s);
|
||||||
} else {
|
} else {
|
||||||
// reduce linear scaling of extrusion vectors so that
|
// reduce linear scaling of extrusion vectors so that
|
||||||
// line width increases by sqrt(2.2).
|
// line width increases by sqrt(2.2).
|
||||||
|
|||||||
@ -130,7 +130,9 @@ public class LineTexRenderer {
|
|||||||
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, layers.vbo.id);
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, layers.vbo.id);
|
||||||
|
|
||||||
float s = pos.scale / div;
|
float scale = (float)pos.getZoomScale();
|
||||||
|
|
||||||
|
float s = scale / div;
|
||||||
|
|
||||||
//GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexID[0]);
|
//GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexID[0]);
|
||||||
|
|
||||||
@ -146,7 +148,7 @@ public class LineTexRenderer {
|
|||||||
GLES20.glUniform1f(hPatternScale, (GLRenderer.COORD_SCALE * line.stipple) / ps);
|
GLES20.glUniform1f(hPatternScale, (GLRenderer.COORD_SCALE * line.stipple) / ps);
|
||||||
GLES20.glUniform1f(hPatternWidth, line.stippleWidth);
|
GLES20.glUniform1f(hPatternWidth, line.stippleWidth);
|
||||||
|
|
||||||
GLES20.glUniform1f(hScale, pos.scale);
|
GLES20.glUniform1f(hScale, scale);
|
||||||
// keep line width fixed
|
// keep line width fixed
|
||||||
GLES20.glUniform1f(hWidth, ll.width / s * COORD_SCALE_BY_DIR_SCALE);
|
GLES20.glUniform1f(hWidth, ll.width / s * COORD_SCALE_BY_DIR_SCALE);
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,9 @@ import org.oscim.renderer.layer.TextItem;
|
|||||||
*/
|
*/
|
||||||
public final class MapTile extends JobTile {
|
public final class MapTile extends JobTile {
|
||||||
|
|
||||||
|
public double x;
|
||||||
|
public double y;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tile data set by TileGenerator.
|
* Tile data set by TileGenerator.
|
||||||
*/
|
*/
|
||||||
@ -73,6 +76,8 @@ public final class MapTile extends JobTile {
|
|||||||
|
|
||||||
MapTile(int tileX, int tileY, byte zoomLevel) {
|
MapTile(int tileX, int tileY, byte zoomLevel) {
|
||||||
super(tileX, tileY, zoomLevel);
|
super(tileX, tileY, zoomLevel);
|
||||||
|
this.x = (double)tileX / (1 << zoomLevel);
|
||||||
|
this.y = (double)tileY / (1 << zoomLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -179,6 +179,8 @@ public final class PolygonRenderer {
|
|||||||
|
|
||||||
int start = cur;
|
int start = cur;
|
||||||
|
|
||||||
|
float scale = (float)pos.getZoomScale();
|
||||||
|
|
||||||
Layer l = layer;
|
Layer l = layer;
|
||||||
for (; l != null && l.type == Layer.POLYGON; l = l.next) {
|
for (; l != null && l.type == Layer.POLYGON; l = l.next) {
|
||||||
PolygonLayer pl = (PolygonLayer) l;
|
PolygonLayer pl = (PolygonLayer) l;
|
||||||
@ -204,13 +206,13 @@ public final class PolygonRenderer {
|
|||||||
|
|
||||||
// draw up to 7 layers into stencil buffer
|
// draw up to 7 layers into stencil buffer
|
||||||
if (cur == STENCIL_BITS - 1) {
|
if (cur == STENCIL_BITS - 1) {
|
||||||
fillPolygons(start, cur, zoom, pos.scale);
|
fillPolygons(start, cur, zoom, scale);
|
||||||
start = cur = 0;
|
start = cur = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur > 0)
|
if (cur > 0)
|
||||||
fillPolygons(start, cur, zoom, pos.scale);
|
fillPolygons(start, cur, zoom, scale);
|
||||||
|
|
||||||
if (clip) {
|
if (clip) {
|
||||||
if (first) {
|
if (first) {
|
||||||
@ -318,7 +320,9 @@ public final class PolygonRenderer {
|
|||||||
glColorMask(false, false, false, false);
|
glColorMask(false, false, false, false);
|
||||||
}
|
}
|
||||||
// always pass stencil test:
|
// always pass stencil test:
|
||||||
glStencilFunc(GL_ALWAYS, 0x00, 0x00);
|
//glStencilFunc(GL_ALWAYS, 0x00, 0x00);
|
||||||
|
glStencilFunc(GL_EQUAL, CLIP_BIT, CLIP_BIT);
|
||||||
|
|
||||||
// write to all bits
|
// write to all bits
|
||||||
glStencilMask(0xFF);
|
glStencilMask(0xFF);
|
||||||
// zero out area to draw to
|
// zero out area to draw to
|
||||||
|
|||||||
@ -122,7 +122,7 @@ public final class TextureRenderer {
|
|||||||
+ " pos = u_proj * (u_mv * vec4(vertex.xy + dir * u_scale, 0.0, 1.0));"
|
+ " pos = u_proj * (u_mv * vec4(vertex.xy + dir * u_scale, 0.0, 1.0));"
|
||||||
+ " } else {" // place as billboard
|
+ " } else {" // place as billboard
|
||||||
+ " vec4 center = u_mv * vec4(vertex.xy, 0.0, 1.0);"
|
+ " vec4 center = u_mv * vec4(vertex.xy, 0.0, 1.0);"
|
||||||
+ " pos = u_proj * (center + vec4(dir * (coord_scale * u_swidth), 0.1, 0.0));"
|
+ " pos = u_proj * (center + vec4(dir * (coord_scale * u_swidth), 0.0, 0.0));"
|
||||||
+ " }"
|
+ " }"
|
||||||
+ " gl_Position = pos;"
|
+ " gl_Position = pos;"
|
||||||
+ " tex_c = tex_coord * div;"
|
+ " tex_c = tex_coord * div;"
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import org.oscim.generator.JobTile;
|
|||||||
import org.oscim.generator.TileDistanceSort;
|
import org.oscim.generator.TileDistanceSort;
|
||||||
import org.oscim.renderer.layer.TextItem;
|
import org.oscim.renderer.layer.TextItem;
|
||||||
import org.oscim.renderer.layer.VertexPool;
|
import org.oscim.renderer.layer.VertexPool;
|
||||||
|
import org.oscim.utils.FastMath;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
import org.oscim.view.MapViewPosition;
|
import org.oscim.view.MapViewPosition;
|
||||||
|
|
||||||
@ -42,6 +43,8 @@ import android.util.Log;
|
|||||||
*/
|
*/
|
||||||
public class TileManager {
|
public class TileManager {
|
||||||
static final String TAG = TileManager.class.getSimpleName();
|
static final String TAG = TileManager.class.getSimpleName();
|
||||||
|
private final static int MAX_ZOOMLEVEL = 17;
|
||||||
|
private final static int MIN_ZOOMLEVEL = 2;
|
||||||
|
|
||||||
// limit number tiles with new data not uploaded to GL
|
// limit number tiles with new data not uploaded to GL
|
||||||
// TODO this should depend on the number of tiles displayed
|
// TODO this should depend on the number of tiles displayed
|
||||||
@ -148,10 +151,10 @@ public class TileManager {
|
|||||||
* 2. Add not yet loaded (or loading) tiles to JobQueue.
|
* 2. Add not yet loaded (or loading) tiles to JobQueue.
|
||||||
* 3. Manage cache
|
* 3. Manage cache
|
||||||
*
|
*
|
||||||
* @param mapPosition
|
* @param pos
|
||||||
* current MapPosition
|
* current MapPosition
|
||||||
*/
|
*/
|
||||||
public synchronized void update(MapPosition mapPosition) {
|
public synchronized void update(MapPosition pos) {
|
||||||
// clear JobQueue and set tiles to state == NONE.
|
// clear JobQueue and set tiles to state == NONE.
|
||||||
// one could also append new tiles and sort in JobQueue
|
// one could also append new tiles and sort in JobQueue
|
||||||
// but this has the nice side-effect that MapWorkers dont
|
// but this has the nice side-effect that MapWorkers dont
|
||||||
@ -162,22 +165,38 @@ public class TileManager {
|
|||||||
|
|
||||||
// scale and translate projection to tile coordinates
|
// scale and translate projection to tile coordinates
|
||||||
// load some tiles more than currently visible (* 0.75)
|
// load some tiles more than currently visible (* 0.75)
|
||||||
float scale = mapPosition.scale * 0.75f;
|
// float scale = mapPosition.scale * 0.75f;
|
||||||
float tileScale = scale * Tile.TILE_SIZE;
|
// float tileScale = scale * Tile.TILE_SIZE;
|
||||||
double px = mapPosition.x * scale;
|
// double px = mapPosition.x * scale;
|
||||||
double py = mapPosition.y * scale;
|
// double py = mapPosition.y * scale;
|
||||||
|
//
|
||||||
|
// float[] coords = mTileCoords;
|
||||||
|
// mMapViewPosition.getMapViewProjection(coords);
|
||||||
|
// for (int i = 0; i < 8; i += 2) {
|
||||||
|
// coords[i + 0] = (float)(px + coords[i + 0]) / tileScale;
|
||||||
|
// coords[i + 1] = (float)(py + coords[i + 1]) / tileScale;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// scale and translate projection to tile coordinates
|
||||||
|
// load some tiles more than currently visible (* 0.75)
|
||||||
|
double scale = pos.scale * 0.75f;
|
||||||
|
double curScale = Tile.TILE_SIZE * scale;
|
||||||
|
int zoomLevel = FastMath.clamp(pos.zoomLevel, MIN_ZOOMLEVEL, MAX_ZOOMLEVEL);
|
||||||
|
|
||||||
|
double tileScale = Tile.TILE_SIZE * (scale / (1 << zoomLevel));
|
||||||
|
|
||||||
float[] coords = mTileCoords;
|
float[] coords = mTileCoords;
|
||||||
mMapViewPosition.getMapViewProjection(coords);
|
mMapViewPosition.getMapViewProjection(coords);
|
||||||
|
|
||||||
for (int i = 0; i < 8; i += 2) {
|
for (int i = 0; i < 8; i += 2) {
|
||||||
coords[i + 0] = (float)(px + coords[i + 0]) / tileScale;
|
coords[i + 0] = (float) ((pos.x * curScale + coords[i + 0]) / tileScale);
|
||||||
coords[i + 1] = (float)(py + coords[i + 1]) / tileScale;
|
coords[i + 1] = (float) ((pos.y * curScale + coords[i + 1]) / tileScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// scan visible tiles. callback function calls 'addTile'
|
// scan visible tiles. callback function calls 'addTile'
|
||||||
// which sets mNewTiles
|
// which sets mNewTiles
|
||||||
mNewTiles.cnt = 0;
|
mNewTiles.cnt = 0;
|
||||||
mScanBox.scan(coords, mapPosition.zoomLevel);
|
mScanBox.scan(coords, zoomLevel);
|
||||||
|
|
||||||
MapTile[] newTiles = mNewTiles.tiles;
|
MapTile[] newTiles = mNewTiles.tiles;
|
||||||
MapTile[] curTiles = mCurrentTiles.tiles;
|
MapTile[] curTiles = mCurrentTiles.tiles;
|
||||||
@ -225,7 +244,7 @@ public class TileManager {
|
|||||||
|
|
||||||
JobTile[] jobs = new JobTile[mJobs.size()];
|
JobTile[] jobs = new JobTile[mJobs.size()];
|
||||||
jobs = mJobs.toArray(jobs);
|
jobs = mJobs.toArray(jobs);
|
||||||
updateTileDistances(jobs, jobs.length, mapPosition);
|
updateTileDistances(jobs, jobs.length, pos);
|
||||||
|
|
||||||
// sets tiles to state == LOADING
|
// sets tiles to state == LOADING
|
||||||
mMapView.addJobs(jobs);
|
mMapView.addJobs(jobs);
|
||||||
@ -237,7 +256,7 @@ public class TileManager {
|
|||||||
if (remove > CACHE_THRESHOLD ||
|
if (remove > CACHE_THRESHOLD ||
|
||||||
mTilesForUpload > MAX_TILES_IN_QUEUE)
|
mTilesForUpload > MAX_TILES_IN_QUEUE)
|
||||||
|
|
||||||
limitCache(mapPosition, remove);
|
limitCache(pos, remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to keep track of TileSets to clear on reset...
|
// need to keep track of TileSets to clear on reset...
|
||||||
@ -295,7 +314,7 @@ public class TileManager {
|
|||||||
tile = QuadTree.getTile(x, y, zoomLevel);
|
tile = QuadTree.getTile(x, y, zoomLevel);
|
||||||
|
|
||||||
if (tile == null) {
|
if (tile == null) {
|
||||||
tile = new MapTile(x, y, (byte)zoomLevel);
|
tile = new MapTile(x, y, (byte) zoomLevel);
|
||||||
QuadTree.add(tile);
|
QuadTree.add(tile);
|
||||||
mJobs.add(tile);
|
mJobs.add(tile);
|
||||||
addToCache(tile);
|
addToCache(tile);
|
||||||
@ -389,11 +408,13 @@ public class TileManager {
|
|||||||
|
|
||||||
private static void updateTileDistances(Object[] tiles, int size, MapPosition mapPosition) {
|
private static void updateTileDistances(Object[] tiles, int size, MapPosition mapPosition) {
|
||||||
// TODO there is probably a better quad-tree distance function
|
// TODO there is probably a better quad-tree distance function
|
||||||
double x = mapPosition.x;
|
|
||||||
double y = mapPosition.y;
|
|
||||||
int zoom = mapPosition.zoomLevel;
|
int zoom = mapPosition.zoomLevel;
|
||||||
int h = Tile.TILE_SIZE >> 1;
|
double x = mapPosition.x * (1 << zoom);
|
||||||
long center = h << zoom;
|
double y = mapPosition.y * (1 << zoom);
|
||||||
|
|
||||||
|
final float h = 0.5f;
|
||||||
|
long center = (long)(h * (1 << zoom));
|
||||||
|
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
JobTile t = (JobTile) tiles[i];
|
JobTile t = (JobTile) tiles[i];
|
||||||
@ -405,16 +426,16 @@ public class TileManager {
|
|||||||
dz = 0;
|
dz = 0;
|
||||||
|
|
||||||
if (diff == 0) {
|
if (diff == 0) {
|
||||||
dx = (t.pixelX + h) - x;
|
dx = (t.tileX + h) - x;
|
||||||
dy = (t.pixelY + h) - y;
|
dy = (t.tileY + h) - y;
|
||||||
scale = 0.5f;
|
scale = 0.5f;
|
||||||
} else if (diff > 0) {
|
} else if (diff > 0) {
|
||||||
// tile zoom level is greater than current
|
// tile zoom level is greater than current
|
||||||
// NB: distance increase by the factor 2
|
// NB: distance increase by the factor 2
|
||||||
// with each zoom-level, so that children
|
// with each zoom-level, so that children
|
||||||
// will be kept less likely than parent tiles.
|
// will be kept less likely than parent tiles.
|
||||||
dx = (t.pixelX + h) - x * (1 << diff);
|
dx = (t.tileX + h) - x * (1 << diff);
|
||||||
dy = (t.pixelY + h) - y * (1 << diff);
|
dy = (t.tileY + h) - y * (1 << diff);
|
||||||
// add tilesize/2 with each zoom-level
|
// add tilesize/2 with each zoom-level
|
||||||
// so that children near the current
|
// so that children near the current
|
||||||
// map position but a few levels above
|
// map position but a few levels above
|
||||||
@ -424,8 +445,8 @@ public class TileManager {
|
|||||||
} else {
|
} else {
|
||||||
diff = -diff;
|
diff = -diff;
|
||||||
// tile zoom level is smaller than current
|
// tile zoom level is smaller than current
|
||||||
dx = (t.pixelX + h) - x / (1 << diff);
|
dx = (t.tileX + h) - x / (1 << diff);
|
||||||
dy = (t.pixelY + h) - y / (1 << diff);
|
dy = (t.tileY + h) - y / (1 << diff);
|
||||||
dz = diff * h;
|
dz = diff * h;
|
||||||
scale = 0.5f * (1 << diff);
|
scale = 0.5f * (1 << diff);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import static android.opengl.GLES20.glStencilMask;
|
|||||||
import static org.oscim.generator.JobTile.STATE_READY;
|
import static org.oscim.generator.JobTile.STATE_READY;
|
||||||
|
|
||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.renderer.GLRenderer.Matrices;
|
import org.oscim.renderer.GLRenderer.Matrices;
|
||||||
import org.oscim.renderer.layer.Layer;
|
import org.oscim.renderer.layer.Layer;
|
||||||
import org.oscim.utils.FastMath;
|
import org.oscim.utils.FastMath;
|
||||||
@ -68,21 +69,25 @@ public class TileRenderer {
|
|||||||
drawTile(t, pos);
|
drawTile(t, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double scale = pos.getZoomScale();
|
||||||
|
|
||||||
// Draw parent or children as proxy for visibile tiles that dont
|
// Draw parent or children as proxy for visibile tiles that dont
|
||||||
// have data yet. Proxies are clipped to the region where nothing
|
// have data yet. Proxies are clipped to the region where nothing
|
||||||
// was drawn to depth buffer.
|
// was drawn to depth buffer.
|
||||||
// TODO draw proxies for placeholder
|
// TODO draw proxies for placeholder
|
||||||
for (int i = 0; i < tileCnt; i++) {
|
for (int i = 0; i < tileCnt; i++) {
|
||||||
MapTile t = tiles[i];
|
MapTile t = tiles[i];
|
||||||
if (t.isVisible && (t.state != STATE_READY) && (t.holder == null))
|
if (t.isVisible && (t.state != STATE_READY) && (t.holder == null)){
|
||||||
drawProxyTile(t, pos, true);
|
boolean preferParent = (scale > 1.5) || (pos.zoomLevel - t.zoomLevel < 0);
|
||||||
|
drawProxyTile(t, pos, true, preferParent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw grandparents
|
// Draw grandparents
|
||||||
for (int i = 0; i < tileCnt; i++) {
|
for (int i = 0; i < tileCnt; i++) {
|
||||||
MapTile t = tiles[i];
|
MapTile t = tiles[i];
|
||||||
if (t.isVisible && (t.state != STATE_READY) && (t.holder == null))
|
if (t.isVisible && (t.state != STATE_READY) && (t.holder == null))
|
||||||
drawProxyTile(t, pos, false);
|
drawProxyTile(t, pos, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure stencil buffer write is disabled
|
// make sure stencil buffer write is disabled
|
||||||
@ -116,13 +121,18 @@ public class TileRenderer {
|
|||||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, t.layers.vbo.id);
|
GLES20.glBindBuffer(GL_ARRAY_BUFFER, t.layers.vbo.id);
|
||||||
|
|
||||||
// place tile relative to map position
|
// place tile relative to map position
|
||||||
float div = FastMath.pow(tile.zoomLevel - pos.zoomLevel);
|
int z = tile.zoomLevel;
|
||||||
float x = (float) (tile.pixelX - pos.x * div);
|
|
||||||
float y = (float) (tile.pixelY - pos.y * div);
|
float div = FastMath.pow(z - pos.zoomLevel);
|
||||||
float scale = pos.scale / div;
|
|
||||||
|
double curScale = Tile.TILE_SIZE * pos.scale;
|
||||||
|
double scale = (pos.scale / (1 << z));
|
||||||
|
|
||||||
|
float x = (float) ((tile.x - pos.x) * curScale);
|
||||||
|
float y = (float) ((tile.y - pos.y) * curScale);
|
||||||
|
|
||||||
Matrices m = mMatrices;
|
Matrices m = mMatrices;
|
||||||
m.mvp.setTransScale(x * scale, y * scale, scale / GLRenderer.COORD_SCALE);
|
m.mvp.setTransScale(x, y, (float)(scale / GLRenderer.COORD_SCALE));
|
||||||
|
|
||||||
m.mvp.multiplyMM(mProjMatrix, m.mvp);
|
m.mvp.multiplyMM(mProjMatrix, m.mvp);
|
||||||
|
|
||||||
@ -168,7 +178,8 @@ public class TileRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clear clip-region and could also draw 'fade-effect'
|
// clear clip-region and could also draw 'fade-effect'
|
||||||
PolygonRenderer.drawOver(m, true, 0x22000000);
|
//PolygonRenderer.drawOver(m, true, 0x22000000);
|
||||||
|
PolygonRenderer.drawOver(m, false, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int drawProxyChild(MapTile tile, MapPosition pos) {
|
private static int drawProxyChild(MapTile tile, MapPosition pos) {
|
||||||
@ -187,12 +198,14 @@ public class TileRenderer {
|
|||||||
return drawn;
|
return drawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void drawProxyTile(MapTile tile, MapPosition pos, boolean parent) {
|
// just FIXME!
|
||||||
int diff = pos.zoomLevel - tile.zoomLevel;
|
private static void drawProxyTile(MapTile tile, MapPosition pos, boolean parent, boolean preferParent) {
|
||||||
|
//int diff = pos.zoomLevel - tile.zoomLevel;
|
||||||
QuadTree r = tile.rel;
|
QuadTree r = tile.rel;
|
||||||
MapTile proxy;
|
MapTile proxy;
|
||||||
|
|
||||||
if (pos.scale > 1.5f || diff < 0) {
|
|
||||||
|
if (!preferParent) {
|
||||||
// prefer drawing children
|
// prefer drawing children
|
||||||
if (drawProxyChild(tile, pos) == 4)
|
if (drawProxyChild(tile, pos) == 4)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -46,35 +46,36 @@ public abstract class BasicOverlay extends RenderOverlay {
|
|||||||
* use synchronized when modifying layers
|
* use synchronized when modifying layers
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized void render(MapPosition pos, Matrices m) {
|
public synchronized void render(MapPosition curPos, Matrices m) {
|
||||||
|
MapPosition pos = mMapPosition;
|
||||||
|
|
||||||
float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel);
|
float div = FastMath.pow(pos.zoomLevel - curPos.zoomLevel);
|
||||||
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, layers.vbo.id);
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, layers.vbo.id);
|
||||||
GLState.test(false, false);
|
GLState.test(false, false);
|
||||||
|
|
||||||
if (layers.baseLayers != null) {
|
if (layers.baseLayers != null) {
|
||||||
setMatrix(pos, m, true);
|
setMatrix(curPos, m, true);
|
||||||
|
|
||||||
for (Layer l = layers.baseLayers; l != null;) {
|
for (Layer l = layers.baseLayers; l != null;) {
|
||||||
switch (l.type) {
|
switch (l.type) {
|
||||||
case Layer.POLYGON:
|
case Layer.POLYGON:
|
||||||
l = PolygonRenderer.draw(pos, l, m, true, false);
|
l = PolygonRenderer.draw(curPos, l, m, true, false);
|
||||||
break;
|
break;
|
||||||
case Layer.LINE:
|
case Layer.LINE:
|
||||||
l = LineRenderer.draw(layers, l, pos, m, div, 0);
|
l = LineRenderer.draw(layers, l, curPos, m, div, 0);
|
||||||
break;
|
break;
|
||||||
case Layer.TEXLINE:
|
case Layer.TEXLINE:
|
||||||
l = LineTexRenderer.draw(layers, l, pos, m, div);
|
l = LineTexRenderer.draw(layers, l, curPos, m, div);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layers.textureLayers != null) {
|
if (layers.textureLayers != null) {
|
||||||
setMatrix(pos, m, false);
|
setMatrix(curPos, m, false);
|
||||||
|
|
||||||
float scale = (mMapPosition.scale / pos.scale) * div;
|
float scale = (float)(pos.scale / curPos.scale);
|
||||||
|
|
||||||
for (Layer l = layers.textureLayers; l != null;) {
|
for (Layer l = layers.textureLayers; l != null;) {
|
||||||
l = TextureRenderer.draw(l, scale, m);
|
l = TextureRenderer.draw(l, scale, m);
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import java.nio.ByteOrder;
|
|||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.generator.JobTile;
|
import org.oscim.generator.JobTile;
|
||||||
import org.oscim.renderer.GLRenderer;
|
import org.oscim.renderer.GLRenderer;
|
||||||
import org.oscim.renderer.GLRenderer.Matrices;
|
import org.oscim.renderer.GLRenderer.Matrices;
|
||||||
@ -26,7 +27,6 @@ import org.oscim.renderer.GLState;
|
|||||||
import org.oscim.renderer.MapTile;
|
import org.oscim.renderer.MapTile;
|
||||||
import org.oscim.renderer.TileSet;
|
import org.oscim.renderer.TileSet;
|
||||||
import org.oscim.renderer.layer.ExtrusionLayer;
|
import org.oscim.renderer.layer.ExtrusionLayer;
|
||||||
import org.oscim.utils.FastMath;
|
|
||||||
import org.oscim.utils.GlUtils;
|
import org.oscim.utils.GlUtils;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ public class ExtrusionOverlay extends RenderOverlay {
|
|||||||
|
|
||||||
MapTile[] tiles = mTiles;
|
MapTile[] tiles = mTiles;
|
||||||
|
|
||||||
float div = FastMath.pow(tiles[0].zoomLevel - pos.zoomLevel);
|
//float div = FastMath.pow(tiles[0].zoomLevel - pos.zoomLevel);
|
||||||
|
|
||||||
int shaderMode = 1;
|
int shaderMode = 1;
|
||||||
int uExtAlpha = hAlpha[shaderMode];
|
int uExtAlpha = hAlpha[shaderMode];
|
||||||
@ -195,7 +195,7 @@ public class ExtrusionOverlay extends RenderOverlay {
|
|||||||
for (int i = 0; i < mTileCnt; i++) {
|
for (int i = 0; i < mTileCnt; i++) {
|
||||||
ExtrusionLayer el = (ExtrusionLayer) tiles[i].layers.extrusionLayers;
|
ExtrusionLayer el = (ExtrusionLayer) tiles[i].layers.extrusionLayers;
|
||||||
|
|
||||||
setMatrix(pos, m, tiles[i], div, 0);
|
setMatrix(pos, m, tiles[i], 0);
|
||||||
m.mvp.setAsUniform(uExtMatrix);
|
m.mvp.setAsUniform(uExtMatrix);
|
||||||
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID);
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID);
|
||||||
@ -230,7 +230,7 @@ public class ExtrusionOverlay extends RenderOverlay {
|
|||||||
|
|
||||||
GLState.useProgram(shaderProgram[shaderMode]);
|
GLState.useProgram(shaderProgram[shaderMode]);
|
||||||
GLState.enableVertexArrays(uExtVertexPosition, -1);
|
GLState.enableVertexArrays(uExtVertexPosition, -1);
|
||||||
if (pos.scale < 2) {
|
if (pos.scale < (1 << 18)) {
|
||||||
// chances are high that one moves through a building
|
// chances are high that one moves through a building
|
||||||
// with scale > 2 also draw back sides in this case.
|
// with scale > 2 also draw back sides in this case.
|
||||||
GLES20.glEnable(GLES20.GL_CULL_FACE);
|
GLES20.glEnable(GLES20.GL_CULL_FACE);
|
||||||
@ -247,7 +247,7 @@ public class ExtrusionOverlay extends RenderOverlay {
|
|||||||
MapTile t = tiles[i];
|
MapTile t = tiles[i];
|
||||||
ExtrusionLayer el = (ExtrusionLayer) t.layers.extrusionLayers;
|
ExtrusionLayer el = (ExtrusionLayer) t.layers.extrusionLayers;
|
||||||
int d = GLRenderer.depthOffset(t) * 10;
|
int d = GLRenderer.depthOffset(t) * 10;
|
||||||
setMatrix(pos, m, t, div, d);
|
setMatrix(pos, m, t, d);
|
||||||
m.mvp.setAsUniform(uExtMatrix);
|
m.mvp.setAsUniform(uExtMatrix);
|
||||||
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID);
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID);
|
||||||
@ -273,7 +273,7 @@ public class ExtrusionOverlay extends RenderOverlay {
|
|||||||
|
|
||||||
GLES20.glDepthFunc(GLES20.GL_EQUAL);
|
GLES20.glDepthFunc(GLES20.GL_EQUAL);
|
||||||
int d = GLRenderer.depthOffset(t) * 10;
|
int d = GLRenderer.depthOffset(t) * 10;
|
||||||
setMatrix(pos, m, t, div, d);
|
setMatrix(pos, m, t, d);
|
||||||
m.mvp.setAsUniform(uExtMatrix);
|
m.mvp.setAsUniform(uExtMatrix);
|
||||||
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID);
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID);
|
||||||
@ -316,19 +316,28 @@ public class ExtrusionOverlay extends RenderOverlay {
|
|||||||
tiles[i] = null;
|
tiles[i] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos.scale < 2)
|
if (pos.scale < (1 << 18))
|
||||||
GLES20.glDisable(GLES20.GL_CULL_FACE);
|
GLES20.glDisable(GLES20.GL_CULL_FACE);
|
||||||
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setMatrix(MapPosition mapPosition, Matrices m,
|
private static void setMatrix(MapPosition pos, Matrices m,
|
||||||
MapTile tile, float div, int delta) {
|
MapTile tile, int delta) {
|
||||||
|
|
||||||
float x = (float) (tile.pixelX - mapPosition.x * div);
|
int z = tile.zoomLevel;
|
||||||
float y = (float) (tile.pixelY - mapPosition.y * div);
|
double curScale = Tile.TILE_SIZE * pos.scale;
|
||||||
float scale = mapPosition.scale / div;
|
float scale = (float)(pos.scale / (1 << z));
|
||||||
|
|
||||||
m.mvp.setTransScale(x * scale, y * scale, scale / GLRenderer.COORD_SCALE);
|
float x = (float) ((tile.x - pos.x) * curScale);
|
||||||
|
float y = (float) ((tile.y - pos.y) * curScale);
|
||||||
|
m.mvp.setTransScale(x, y, scale / GLRenderer.COORD_SCALE);
|
||||||
|
|
||||||
|
// float x = (float) (tile.pixelX - mapPosition.x * div);
|
||||||
|
// float y = (float) (tile.pixelY - mapPosition.y * div);
|
||||||
|
// float scale = mapPosition.scale / div;
|
||||||
|
//
|
||||||
|
// m.mvp.setTransScale(x * scale, y * scale, scale / GLRenderer.COORD_SCALE);
|
||||||
|
|
||||||
// scale height
|
// scale height
|
||||||
m.mvp.setValue(10, scale / 10);
|
m.mvp.setValue(10, scale / 10);
|
||||||
|
|||||||
@ -93,7 +93,6 @@ public class GridOverlay extends BasicOverlay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tl.prepare();
|
tl.prepare();
|
||||||
|
|
||||||
layers.textureLayers = tl;
|
layers.textureLayers = tl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,30 +100,28 @@ public class GridOverlay extends BasicOverlay {
|
|||||||
private int mCurY = -1;
|
private int mCurY = -1;
|
||||||
private int mCurZ = -1;
|
private int mCurZ = -1;
|
||||||
|
|
||||||
private boolean finished;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void update(MapPosition curPos, boolean positionChanged,
|
public synchronized void update(MapPosition curPos, boolean positionChanged,
|
||||||
boolean tilesChanged, Matrices matrices) {
|
boolean tilesChanged, Matrices matrices) {
|
||||||
|
|
||||||
mMapPosition.copy(curPos);
|
int z = 1 << curPos.zoomLevel;
|
||||||
|
|
||||||
// fix map position to tile coordinates
|
int x = (int) (curPos.x * z);
|
||||||
float size = Tile.TILE_SIZE;
|
int y = (int) (curPos.y * z);
|
||||||
int x = (int) (mMapPosition.x / size);
|
|
||||||
int y = (int) (mMapPosition.y / size);
|
|
||||||
mMapPosition.x = x * size;
|
|
||||||
mMapPosition.y = y * size;
|
|
||||||
|
|
||||||
if (!finished)
|
|
||||||
mMapPosition.scale = 1;
|
|
||||||
|
|
||||||
// update layers when map moved by at least one tile
|
// update layers when map moved by at least one tile
|
||||||
if (x != mCurX || y != mCurY || mMapPosition.zoomLevel != mCurZ) {
|
if (x != mCurX || y != mCurY || z != mCurZ) {
|
||||||
|
|
||||||
|
MapPosition pos = mMapPosition;
|
||||||
|
|
||||||
|
pos.copy(curPos);
|
||||||
|
pos.x = (double) x / z;
|
||||||
|
pos.y = (double) y / z;
|
||||||
|
pos.scale = z;
|
||||||
|
|
||||||
mCurX = x;
|
mCurX = x;
|
||||||
mCurY = y;
|
mCurY = y;
|
||||||
mCurZ = mMapPosition.zoomLevel;
|
mCurZ = z;
|
||||||
|
|
||||||
layers.clear();
|
layers.clear();
|
||||||
|
|
||||||
@ -134,9 +131,7 @@ public class GridOverlay extends BasicOverlay {
|
|||||||
ll.addLine(mPoints, mIndex, false);
|
ll.addLine(mPoints, mIndex, false);
|
||||||
|
|
||||||
addLabels(x, y, mCurZ);
|
addLabels(x, y, mCurZ);
|
||||||
|
|
||||||
newData = true;
|
newData = true;
|
||||||
finished = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,6 @@ import org.oscim.core.MapPosition;
|
|||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.renderer.GLRenderer;
|
import org.oscim.renderer.GLRenderer;
|
||||||
import org.oscim.renderer.GLRenderer.Matrices;
|
import org.oscim.renderer.GLRenderer.Matrices;
|
||||||
import org.oscim.utils.FastMath;
|
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
|
|
||||||
public abstract class RenderOverlay {
|
public abstract class RenderOverlay {
|
||||||
@ -51,7 +50,8 @@ public abstract class RenderOverlay {
|
|||||||
* true when current tiles changed
|
* true when current tiles changed
|
||||||
* @param matrices TODO
|
* @param matrices TODO
|
||||||
*/
|
*/
|
||||||
public abstract void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged, Matrices matrices);
|
public abstract void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged,
|
||||||
|
Matrices matrices);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called 2. compile everything for drawing
|
* called 2. compile everything for drawing
|
||||||
@ -70,44 +70,40 @@ public abstract class RenderOverlay {
|
|||||||
public abstract void render(MapPosition pos, Matrices m);
|
public abstract void render(MapPosition pos, Matrices m);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility: set m.mvp matrix relative to the difference of current MapPosition
|
* Utility: set m.mvp matrix relative to the difference of current
|
||||||
|
* MapPosition
|
||||||
* and the last updated Overlay MapPosition
|
* and the last updated Overlay MapPosition
|
||||||
*
|
*
|
||||||
* @param curPos ...
|
* @param curPos
|
||||||
* @param m ...
|
* current MapPosition
|
||||||
|
* @param m
|
||||||
|
* current Matrices
|
||||||
* @param project
|
* @param project
|
||||||
* apply view and projection, or just view otherwise
|
* apply view and projection, or just view otherwise
|
||||||
*/
|
*/
|
||||||
protected void setMatrix(MapPosition curPos, Matrices m, boolean project) {
|
protected void setMatrix(MapPosition curPos, Matrices m, boolean project) {
|
||||||
MapPosition oPos = mMapPosition;
|
MapPosition oPos = mMapPosition;
|
||||||
|
|
||||||
float div = FastMath.pow(oPos.zoomLevel - curPos.zoomLevel);
|
double tileScale = Tile.TILE_SIZE * curPos.scale;
|
||||||
|
|
||||||
// translate relative to map center
|
double x = oPos.x - curPos.x;
|
||||||
float x = (float) (oPos.x - curPos.x * div);
|
double y = oPos.y - curPos.y;
|
||||||
float y = (float) (oPos.y - curPos.y * div);
|
|
||||||
|
|
||||||
// flip around date-line
|
// wrap around date-line
|
||||||
float max = (Tile.TILE_SIZE << oPos.zoomLevel);
|
while (x < 0)
|
||||||
if (x < -max / 2)
|
x += 1.0;
|
||||||
x = max + x;
|
while (x > 1)
|
||||||
else if (x > max / 2)
|
x -= 1.0;
|
||||||
x = x - max;
|
|
||||||
|
|
||||||
// scale to current tile world coordinates
|
m.mvp.setTransScale((float) (x * tileScale), (float) (y * tileScale),
|
||||||
float scale = curPos.scale / div;
|
(float) ((curPos.scale / oPos.scale) / GLRenderer.COORD_SCALE));
|
||||||
|
|
||||||
// set scale to be relative to current scale
|
|
||||||
float s = (curPos.scale / oPos.scale) / div;
|
|
||||||
|
|
||||||
m.mvp.setTransScale(x * scale, y * scale,
|
|
||||||
s / GLRenderer.COORD_SCALE);
|
|
||||||
|
|
||||||
m.mvp.multiplyMM(project ? m.viewproj : m.view, m.mvp);
|
m.mvp.multiplyMM(project ? m.viewproj : m.view, m.mvp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility: set m.mvp matrix relative to the difference of current MapPosition
|
* Utility: set m.mvp matrix relative to the difference of current
|
||||||
|
* MapPosition
|
||||||
* and the last updated Overlay MapPosition and add m.viewproj
|
* and the last updated Overlay MapPosition and add m.viewproj
|
||||||
*
|
*
|
||||||
* @param curPos ...
|
* @param curPos ...
|
||||||
@ -116,13 +112,4 @@ public abstract class RenderOverlay {
|
|||||||
protected void setMatrix(MapPosition curPos, Matrices m) {
|
protected void setMatrix(MapPosition curPos, Matrices m) {
|
||||||
setMatrix(curPos, m, true);
|
setMatrix(curPos, m, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Utility: update mMapPosition
|
|
||||||
// *
|
|
||||||
// * @return true if position has changed
|
|
||||||
// */
|
|
||||||
// protected boolean updateMapPosition() {
|
|
||||||
// return mMapView.getMapViewPosition().getMapPosition(mMapPosition);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -246,6 +246,7 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
|
|
||||||
private Layers mDebugLayer;
|
private Layers mDebugLayer;
|
||||||
private final static float[] mDebugPoints = new float[4];
|
private final static float[] mDebugPoints = new float[4];
|
||||||
|
|
||||||
//private final Matrix4 mMVP = new Matrix4();
|
//private final Matrix4 mMVP = new Matrix4();
|
||||||
|
|
||||||
//void addTile(MapTile t) {
|
//void addTile(MapTile t) {
|
||||||
@ -313,9 +314,15 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
// this scales MapPosition to the zoomlevel of mTiles...
|
// this scales MapPosition to the zoomlevel of mTiles...
|
||||||
// TODO create a helper function in MapPosition
|
// TODO create a helper function in MapPosition
|
||||||
MapTile[] tiles = mTileSet.tiles;
|
MapTile[] tiles = mTileSet.tiles;
|
||||||
|
|
||||||
|
//int zoom = tiles[0].zoomLevel;
|
||||||
|
|
||||||
int diff = tiles[0].zoomLevel - pos.zoomLevel;
|
int diff = tiles[0].zoomLevel - pos.zoomLevel;
|
||||||
float div = FastMath.pow(diff);
|
float div = FastMath.pow(diff);
|
||||||
float scale = pos.scale * div;
|
|
||||||
|
double scale = pos.getZoomScale() * div;
|
||||||
|
|
||||||
|
//float scale = (float)(pos.absScale / (1 << zoom) );
|
||||||
|
|
||||||
double angle = Math.toRadians(pos.angle);
|
double angle = Math.toRadians(pos.angle);
|
||||||
float cos = (float) Math.cos(angle);
|
float cos = (float) Math.cos(angle);
|
||||||
@ -330,11 +337,17 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
|
|
||||||
mRelabelCnt++;
|
mRelabelCnt++;
|
||||||
|
|
||||||
|
double tileX = (pos.x * (Tile.TILE_SIZE << pos.zoomLevel));
|
||||||
|
double tileY = (pos.y * (Tile.TILE_SIZE << pos.zoomLevel));
|
||||||
|
|
||||||
for (l = mPrevLabels; l != null;) {
|
for (l = mPrevLabels; l != null;) {
|
||||||
|
|
||||||
// transform screen coordinates to tile coordinates
|
// transform screen coordinates to tile coordinates
|
||||||
float s = FastMath.pow(l.tile.zoomLevel - pos.zoomLevel);
|
float s = FastMath.pow(l.tile.zoomLevel - pos.zoomLevel);
|
||||||
float sscale = pos.scale / s;
|
|
||||||
|
//float sscale = (float)((1 << l.tile.zoomLevel) / pos.absScale);
|
||||||
|
|
||||||
|
float sscale = (float) (pos.getZoomScale() / s);
|
||||||
|
|
||||||
if (l.width > l.length * sscale) {
|
if (l.width > l.length * sscale) {
|
||||||
//Log.d(TAG, "- scale " + lp + " " + s + " " + sscale + " " + lp.length + " " + lp.width);
|
//Log.d(TAG, "- scale " + lp + " " + s + " " + sscale + " " + lp.length + " " + lp.width);
|
||||||
@ -342,8 +355,8 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float dx = (float) (l.tile.pixelX - pos.x * s);
|
float dx = (float) (l.tile.tileX * Tile.TILE_SIZE - tileX * s);
|
||||||
float dy = (float) (l.tile.pixelY - pos.y * s);
|
float dy = (float) (l.tile.tileY * Tile.TILE_SIZE - tileY * s);
|
||||||
|
|
||||||
// flip around date-line
|
// flip around date-line
|
||||||
if (dx > maxx)
|
if (dx > maxx)
|
||||||
@ -399,8 +412,8 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
if (t.state != JobTile.STATE_READY)
|
if (t.state != JobTile.STATE_READY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
float dx = (float) (t.pixelX - pos.x);
|
float dx = (float) (t.tileX * Tile.TILE_SIZE - tileX);
|
||||||
float dy = (float) (t.pixelY - pos.y);
|
float dy = (float) (t.tileY * Tile.TILE_SIZE - tileY);
|
||||||
|
|
||||||
// flip around date-line
|
// flip around date-line
|
||||||
if (dx > maxx)
|
if (dx > maxx)
|
||||||
@ -422,7 +435,7 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
l.clone(ti);
|
l.clone(ti);
|
||||||
l.move(ti, dx, dy, scale);
|
l.move(ti, dx, dy, (float) scale);
|
||||||
|
|
||||||
// set line endpoints relative to view to be able to
|
// set line endpoints relative to view to be able to
|
||||||
// check intersections with label from other tiles
|
// check intersections with label from other tiles
|
||||||
@ -448,7 +461,7 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
overlaps = checkOverlap(tl, l);
|
overlaps = checkOverlap(tl, l);
|
||||||
|
|
||||||
if (dbg != null)
|
if (dbg != null)
|
||||||
addDebugBox(dbg, l, ti, overlaps, false, scale);
|
addDebugBox(dbg, l, ti, overlaps, false, (float) scale);
|
||||||
|
|
||||||
if (overlaps == 0) {
|
if (overlaps == 0) {
|
||||||
tl.addText(l);
|
tl.addText(l);
|
||||||
@ -466,8 +479,8 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
if (t.state != JobTile.STATE_READY)
|
if (t.state != JobTile.STATE_READY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
float dx = (float) (t.pixelX - pos.x);
|
float dx = (float) (t.tileX * Tile.TILE_SIZE - tileX);
|
||||||
float dy = (float) (t.pixelY - pos.y);
|
float dy = (float) (t.tileY * Tile.TILE_SIZE - tileY);
|
||||||
|
|
||||||
// flip around date-line
|
// flip around date-line
|
||||||
if (dx > maxx)
|
if (dx > maxx)
|
||||||
@ -484,7 +497,7 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
l = getLabel();
|
l = getLabel();
|
||||||
|
|
||||||
l.clone(ti);
|
l.clone(ti);
|
||||||
l.move(ti, dx, dy, scale);
|
l.move(ti, dx, dy, (float) scale);
|
||||||
if (!nodeIsVisible(l))
|
if (!nodeIsVisible(l))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -678,7 +691,7 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void render(MapPosition pos, Matrices m) {
|
public synchronized void render(MapPosition pos, Matrices m) {
|
||||||
float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel);
|
//float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel);
|
||||||
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, layers.vbo.id);
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, layers.vbo.id);
|
||||||
GLState.test(false, false);
|
GLState.test(false, false);
|
||||||
@ -690,7 +703,10 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
if (l.type == Layer.POLYGON) {
|
if (l.type == Layer.POLYGON) {
|
||||||
l = PolygonRenderer.draw(pos, l, m, true, false);
|
l = PolygonRenderer.draw(pos, l, m, true, false);
|
||||||
} else {
|
} else {
|
||||||
float scale = pos.scale * div;
|
//float scale = pos.getScale() * div;
|
||||||
|
|
||||||
|
float scale = (float) ((1 << mMapPosition.zoomLevel) / pos.scale);
|
||||||
|
|
||||||
l = LineRenderer.draw(layers, l, pos, m, scale, 0);
|
l = LineRenderer.draw(layers, l, pos, m, scale, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -698,7 +714,8 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
|
|
||||||
setMatrix(pos, m);
|
setMatrix(pos, m);
|
||||||
for (Layer l = layers.textureLayers; l != null;) {
|
for (Layer l = layers.textureLayers; l != null;) {
|
||||||
float scale = (mMapPosition.scale / pos.scale) * div;
|
float scale = (float) (mMapPosition.scale / pos.scale);
|
||||||
|
//float scale = (mMapPosition.getScale() / pos.getScale()) * div;
|
||||||
|
|
||||||
l = TextureRenderer.draw(l, scale, m);
|
l = TextureRenderer.draw(l, scale, m);
|
||||||
}
|
}
|
||||||
@ -709,14 +726,22 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
protected void setMatrix(MapPosition curPos, Matrices m) {
|
protected void setMatrix(MapPosition curPos, Matrices m) {
|
||||||
MapPosition oPos = mMapPosition;
|
MapPosition oPos = mMapPosition;
|
||||||
|
|
||||||
float div = FastMath.pow(oPos.zoomLevel - curPos.zoomLevel);
|
double tileScale = Tile.TILE_SIZE * curPos.scale;
|
||||||
float x = (float) (oPos.x - curPos.x * div);
|
double scale = (curPos.scale / oPos.scale);
|
||||||
float y = (float) (oPos.y - curPos.y * div);
|
|
||||||
|
|
||||||
float scale = (curPos.scale / mMapPosition.scale) / div;
|
float x = (float) ((oPos.x - curPos.x) * tileScale);
|
||||||
float s = curPos.scale / div;
|
float y = (float) ((oPos.y - curPos.y) * tileScale);
|
||||||
m.mvp.setTransScale(x * s, y * s,
|
|
||||||
scale / GLRenderer.COORD_SCALE);
|
m.mvp.setTransScale(x, y, (float) (scale / GLRenderer.COORD_SCALE));
|
||||||
|
|
||||||
|
// float div = FastMath.pow(oPos.zoomLevel - curPos.zoomLevel);
|
||||||
|
// float x = (float) (oPos.x - curPos.x * div);
|
||||||
|
// float y = (float) (oPos.y - curPos.y * div);
|
||||||
|
//
|
||||||
|
// float scale = (curPos.getScale() / oPos.getScale()) / div;
|
||||||
|
// float s = curPos.getScale() / div;
|
||||||
|
// m.mvp.setTransScale(x * s, y * s,
|
||||||
|
// scale / GLRenderer.COORD_SCALE);
|
||||||
|
|
||||||
m.mvp.multiplyMM(m.view, m.mvp);
|
m.mvp.multiplyMM(m.view, m.mvp);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ public class Compass {
|
|||||||
mAngle = event.values[0];
|
mAngle = event.values[0];
|
||||||
|
|
||||||
if (mMapView != null) {
|
if (mMapView != null) {
|
||||||
mMapView.getMapPosition().setRotation(-mAngle);
|
mMapView.getMapViewPosition().setRotation(-mAngle);
|
||||||
mMapView.redrawMap(true);
|
mMapView.redrawMap(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,8 +43,8 @@ public class Compass {
|
|||||||
/* package */float mAngle = 0;
|
/* package */float mAngle = 0;
|
||||||
/* package */MapView mMapView;
|
/* package */MapView mMapView;
|
||||||
|
|
||||||
private SensorManager mSensorManager;
|
private final SensorManager mSensorManager;
|
||||||
private Sensor mSensor;
|
private final Sensor mSensor;
|
||||||
|
|
||||||
public Compass(MapActivity mapActivity, MapView mapView) {
|
public Compass(MapActivity mapActivity, MapView mapView) {
|
||||||
mMapView = mapView;
|
mMapView = mapView;
|
||||||
@ -61,6 +61,6 @@ public class Compass {
|
|||||||
|
|
||||||
void disable() {
|
void disable() {
|
||||||
mSensorManager.unregisterListener(mListener);
|
mSensorManager.unregisterListener(mListener);
|
||||||
mMapView.getMapPosition().setRotation(0);
|
mMapView.getMapViewPosition().setRotation(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,14 +40,15 @@ import android.content.SharedPreferences.Editor;
|
|||||||
public abstract class MapActivity extends Activity {
|
public abstract class MapActivity extends Activity {
|
||||||
private static final String KEY_LATITUDE = "latitude";
|
private static final String KEY_LATITUDE = "latitude";
|
||||||
private static final String KEY_LONGITUDE = "longitude";
|
private static final String KEY_LONGITUDE = "longitude";
|
||||||
private static final String KEY_ZOOM_LEVEL = "zoomLevel";
|
private static final String KEY_MAP_SCALE = "map_scale";
|
||||||
|
|
||||||
private static final String PREFERENCES_FILE = "MapActivity";
|
private static final String PREFERENCES_FILE = "MapActivity";
|
||||||
private static final String KEY_THEME = "Theme";
|
private static final String KEY_THEME = "Theme";
|
||||||
|
|
||||||
private static boolean containsMapViewPosition(SharedPreferences sharedPreferences) {
|
private static boolean containsMapViewPosition(SharedPreferences sharedPreferences) {
|
||||||
return sharedPreferences.contains(KEY_LATITUDE)
|
return sharedPreferences.contains(KEY_LATITUDE)
|
||||||
&& sharedPreferences.contains(KEY_LONGITUDE)
|
&& sharedPreferences.contains(KEY_LONGITUDE)
|
||||||
&& sharedPreferences.contains(KEY_ZOOM_LEVEL);
|
&& sharedPreferences.contains(KEY_MAP_SCALE);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MapView mMapView;
|
protected MapView mMapView;
|
||||||
@ -66,14 +67,16 @@ public abstract class MapActivity extends Activity {
|
|||||||
Editor editor = getSharedPreferences(PREFERENCES_FILE, MODE_PRIVATE).edit();
|
Editor editor = getSharedPreferences(PREFERENCES_FILE, MODE_PRIVATE).edit();
|
||||||
editor.clear();
|
editor.clear();
|
||||||
|
|
||||||
// save the map position and zoom level
|
// save the map position
|
||||||
MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
|
MapPosition mapPosition = new MapPosition();
|
||||||
if (mapPosition != null) {
|
|
||||||
GeoPoint geoPoint = new GeoPoint(mapPosition.lat, mapPosition.lon);
|
mMapView.getMapViewPosition().getMapPosition(mapPosition);
|
||||||
editor.putInt(KEY_LATITUDE, geoPoint.latitudeE6);
|
|
||||||
editor.putInt(KEY_LONGITUDE, geoPoint.longitudeE6);
|
GeoPoint geoPoint = mapPosition.getGeoPoint();
|
||||||
editor.putInt(KEY_ZOOM_LEVEL, mapPosition.zoomLevel);
|
|
||||||
}
|
editor.putInt(KEY_LATITUDE, geoPoint.latitudeE6);
|
||||||
|
editor.putInt(KEY_LONGITUDE, geoPoint.longitudeE6);
|
||||||
|
editor.putFloat(KEY_MAP_SCALE, (float)mapPosition.scale);
|
||||||
|
|
||||||
editor.putString(KEY_THEME, mMapView.getRenderTheme());
|
editor.putString(KEY_THEME, mMapView.getRenderTheme());
|
||||||
|
|
||||||
@ -108,12 +111,14 @@ public abstract class MapActivity extends Activity {
|
|||||||
// get and set the map position and zoom level
|
// get and set the map position and zoom level
|
||||||
int latitudeE6 = sharedPreferences.getInt(KEY_LATITUDE, 0);
|
int latitudeE6 = sharedPreferences.getInt(KEY_LATITUDE, 0);
|
||||||
int longitudeE6 = sharedPreferences.getInt(KEY_LONGITUDE, 0);
|
int longitudeE6 = sharedPreferences.getInt(KEY_LONGITUDE, 0);
|
||||||
int zoomLevel = sharedPreferences.getInt(KEY_ZOOM_LEVEL, -1);
|
float scale = sharedPreferences.getFloat(KEY_MAP_SCALE, 1);
|
||||||
|
|
||||||
GeoPoint geoPoint = new GeoPoint(latitudeE6, longitudeE6);
|
|
||||||
MapPosition mapPosition = new MapPosition(geoPoint, (byte) zoomLevel, 1);
|
|
||||||
|
|
||||||
mMapView.getMapViewPosition().setMapCenter(mapPosition);
|
MapPosition mapPosition = new MapPosition();
|
||||||
|
mapPosition.setPosition(latitudeE6 / 1E6, longitudeE6 / 1E6);
|
||||||
|
mapPosition.setScale(scale);
|
||||||
|
|
||||||
|
mMapView.getMapViewPosition().setMapPosition(mapPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
String theme = sharedPreferences.getString(KEY_THEME,
|
String theme = sharedPreferences.getString(KEY_THEME,
|
||||||
|
|||||||
@ -18,7 +18,6 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.core.MercatorProjection;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
@ -173,17 +172,17 @@ public class MapScaleBar {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapPosition currentMapPosition = mMapView.getMapPosition().getMapPosition();
|
// MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
|
||||||
|
//
|
||||||
|
// if (mapPosition.zoomLevel != mMapPosition.zoomLevel) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
if (currentMapPosition.zoomLevel != mMapPosition.zoomLevel) {
|
// double latitudeDiff = Math.abs(mapPosition.lat
|
||||||
return true;
|
// - mMapPosition.lat);
|
||||||
}
|
// if (latitudeDiff > LATITUDE_REDRAW_THRESHOLD) {
|
||||||
|
// return true;
|
||||||
double latitudeDiff = Math.abs(currentMapPosition.lat
|
// }
|
||||||
- mMapPosition.lat);
|
|
||||||
if (latitudeDiff > LATITUDE_REDRAW_THRESHOLD) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -250,31 +249,31 @@ public class MapScaleBar {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mMapPosition = mMapView.getMapPosition().getMapPosition();
|
// mMapPosition = mMapView.getMapPosition().getMapPosition();
|
||||||
double groundResolution = MercatorProjection.calculateGroundResolution(
|
// double groundResolution = MercatorProjection.calculateGroundResolution(
|
||||||
mMapPosition.lat,
|
// mMapPosition.lat,
|
||||||
mMapPosition.zoomLevel);
|
// mMapPosition.zoomLevel);
|
||||||
|
//
|
||||||
int[] scaleBarValues;
|
// int[] scaleBarValues;
|
||||||
if (mImperialUnits) {
|
// if (mImperialUnits) {
|
||||||
groundResolution = groundResolution / METER_FOOT_RATIO;
|
// groundResolution = groundResolution / METER_FOOT_RATIO;
|
||||||
scaleBarValues = SCALE_BAR_VALUES_IMPERIAL;
|
// scaleBarValues = SCALE_BAR_VALUES_IMPERIAL;
|
||||||
} else {
|
// } else {
|
||||||
scaleBarValues = SCALE_BAR_VALUES_METRIC;
|
// scaleBarValues = SCALE_BAR_VALUES_METRIC;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
float scaleBarLength = 0;
|
// float scaleBarLength = 0;
|
||||||
int mapScaleValue = 0;
|
// int mapScaleValue = 0;
|
||||||
|
//
|
||||||
for (int i = 0; i < scaleBarValues.length; ++i) {
|
// for (int i = 0; i < scaleBarValues.length; ++i) {
|
||||||
mapScaleValue = scaleBarValues[i];
|
// mapScaleValue = scaleBarValues[i];
|
||||||
scaleBarLength = mapScaleValue / (float) groundResolution;
|
// scaleBarLength = mapScaleValue / (float) groundResolution;
|
||||||
if (scaleBarLength < (BITMAP_WIDTH - 10)) {
|
// if (scaleBarLength < (BITMAP_WIDTH - 10)) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
redrawMapScaleBitmap(scaleBarLength, mapScaleValue);
|
// redrawMapScaleBitmap(scaleBarLength, mapScaleValue);
|
||||||
mRedrawNeeded = false;
|
mRedrawNeeded = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,6 @@ import org.oscim.generator.MapWorker;
|
|||||||
import org.oscim.generator.TileGenerator;
|
import org.oscim.generator.TileGenerator;
|
||||||
import org.oscim.overlay.BuildingOverlay;
|
import org.oscim.overlay.BuildingOverlay;
|
||||||
import org.oscim.overlay.LabelingOverlay;
|
import org.oscim.overlay.LabelingOverlay;
|
||||||
import org.oscim.overlay.MapLensOverlay;
|
|
||||||
import org.oscim.overlay.Overlay;
|
import org.oscim.overlay.Overlay;
|
||||||
import org.oscim.overlay.OverlayManager;
|
import org.oscim.overlay.OverlayManager;
|
||||||
import org.oscim.renderer.GLRenderer;
|
import org.oscim.renderer.GLRenderer;
|
||||||
@ -175,11 +174,6 @@ public class MapView extends RelativeLayout {
|
|||||||
|
|
||||||
mapActivity.registerMapView(this);
|
mapActivity.registerMapView(this);
|
||||||
|
|
||||||
if (!mMapViewPosition.isValid()) {
|
|
||||||
Log.d(TAG, "set default start position");
|
|
||||||
setMapCenter(new MapPosition(new GeoPoint(0, 0), (byte) 2, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
LayoutParams params = new LayoutParams(
|
LayoutParams params = new LayoutParams(
|
||||||
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
|
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
android.view.ViewGroup.LayoutParams.MATCH_PARENT);
|
android.view.ViewGroup.LayoutParams.MATCH_PARENT);
|
||||||
@ -191,20 +185,63 @@ public class MapView extends RelativeLayout {
|
|||||||
mRotationEnabled = true;
|
mRotationEnabled = true;
|
||||||
|
|
||||||
//mOverlayManager.add(new GenericOverlay(this, new GridOverlay(this)));
|
//mOverlayManager.add(new GenericOverlay(this, new GridOverlay(this)));
|
||||||
mOverlayManager.add(new BuildingOverlay(this));
|
|
||||||
|
|
||||||
|
mOverlayManager.add(new BuildingOverlay(this));
|
||||||
mOverlayManager.add(new LabelingOverlay(this));
|
mOverlayManager.add(new LabelingOverlay(this));
|
||||||
|
|
||||||
|
|
||||||
//mOverlayManager.add(new GenericOverlay(this, new TileOverlay(this)));
|
//mOverlayManager.add(new GenericOverlay(this, new TileOverlay(this)));
|
||||||
mOverlayManager.add(new MapLensOverlay(this));
|
|
||||||
|
|
||||||
//mOverlayManager.add(new GenericOverlay(this, new CustomOverlay(this)));
|
//mOverlayManager.add(new GenericOverlay(this, new CustomOverlay(this)));
|
||||||
|
//mOverlayManager.add(new MapLensOverlay(this));
|
||||||
|
|
||||||
// if (testRegionZoom)
|
|
||||||
// mRegionLookup = new RegionLookup(this);
|
|
||||||
clearMap();
|
clearMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy() {
|
||||||
|
mTileManager.destroy();
|
||||||
|
|
||||||
|
for (MapWorker mapWorker : mMapWorkers) {
|
||||||
|
mapWorker.pause();
|
||||||
|
mapWorker.interrupt();
|
||||||
|
|
||||||
|
mapWorker.getTileGenerator().getMapDatabase().close();
|
||||||
|
|
||||||
|
try {
|
||||||
|
mapWorker.join(10000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// restore the interrupted status
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean mPausing = false;
|
||||||
|
|
||||||
|
void onPause() {
|
||||||
|
mPausing = true;
|
||||||
|
|
||||||
|
Log.d(TAG, "onPause");
|
||||||
|
mJobQueue.clear();
|
||||||
|
mapWorkersPause(true);
|
||||||
|
|
||||||
|
if (this.mCompassEnabled)
|
||||||
|
mCompass.disable();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void onResume() {
|
||||||
|
Log.d(TAG, "onResume");
|
||||||
|
mapWorkersProceed();
|
||||||
|
|
||||||
|
if (this.mCompassEnabled)
|
||||||
|
mCompass.enable();
|
||||||
|
|
||||||
|
mPausing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onStop() {
|
||||||
|
Log.d(TAG, "onStop");
|
||||||
|
//mTileManager.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -243,13 +280,6 @@ public class MapView extends RelativeLayout {
|
|||||||
mGLView.requestRender();
|
mGLView.requestRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the current position and zoom level of this MapView.
|
|
||||||
*/
|
|
||||||
public MapViewPosition getMapPosition() {
|
|
||||||
return mMapViewPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enableRotation(boolean enable) {
|
public void enableRotation(boolean enable) {
|
||||||
mRotationEnabled = enable;
|
mRotationEnabled = enable;
|
||||||
|
|
||||||
@ -356,10 +386,19 @@ public class MapView extends RelativeLayout {
|
|||||||
if (startPos == null)
|
if (startPos == null)
|
||||||
startPos = new GeoPoint(0, 0);
|
startPos = new GeoPoint(0, 0);
|
||||||
|
|
||||||
if (mapInfo.startZoomLevel != null)
|
MapPosition mapPosition = new MapPosition();
|
||||||
return new MapPosition(startPos, (mapInfo.startZoomLevel).byteValue(), 1);
|
mapPosition.setPosition(startPos);
|
||||||
|
|
||||||
return new MapPosition(startPos, (byte) 12, 1);
|
if (mapInfo.startZoomLevel == null)
|
||||||
|
mapPosition.setZoomLevel(12);
|
||||||
|
else
|
||||||
|
mapPosition.setZoomLevel((mapInfo.startZoomLevel).byteValue());
|
||||||
|
|
||||||
|
return mapPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMapPosition(MapPosition mapPosition) {
|
||||||
|
mMapViewPosition.setMapPosition(mapPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -505,95 +544,6 @@ public class MapView extends RelativeLayout {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy() {
|
|
||||||
for (MapWorker mapWorker : mMapWorkers) {
|
|
||||||
mapWorker.pause();
|
|
||||||
mapWorker.interrupt();
|
|
||||||
|
|
||||||
mapWorker.getTileGenerator().getMapDatabase().close();
|
|
||||||
|
|
||||||
try {
|
|
||||||
mapWorker.join(10000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// restore the interrupted status
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean mPausing = false;
|
|
||||||
|
|
||||||
void onPause() {
|
|
||||||
mPausing = true;
|
|
||||||
|
|
||||||
Log.d(TAG, "onPause");
|
|
||||||
mJobQueue.clear();
|
|
||||||
mapWorkersPause(true);
|
|
||||||
|
|
||||||
if (this.mCompassEnabled)
|
|
||||||
mCompass.disable();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void onResume() {
|
|
||||||
Log.d(TAG, "onResume");
|
|
||||||
mapWorkersProceed();
|
|
||||||
|
|
||||||
if (this.mCompassEnabled)
|
|
||||||
mCompass.enable();
|
|
||||||
|
|
||||||
mPausing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onStop() {
|
|
||||||
Log.d(TAG, "onStop");
|
|
||||||
mTileManager.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the maximum possible zoom level.
|
|
||||||
*/
|
|
||||||
byte getMaximumPossibleZoomLevel() {
|
|
||||||
return (byte) MapViewPosition.MAX_ZOOMLEVEL;
|
|
||||||
// Math.min(mMapZoomControls.getZoomLevelMax(),
|
|
||||||
// mMapGenerator.getZoomLevelMax());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the current center position of this MapView is valid,
|
|
||||||
* false otherwise.
|
|
||||||
*/
|
|
||||||
boolean hasValidCenter() {
|
|
||||||
MapInfo mapInfo;
|
|
||||||
|
|
||||||
if (!mMapViewPosition.isValid())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ((mapInfo = mMapDatabase.getMapInfo()) == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!mapInfo.boundingBox.contains(getMapPosition().getMapCenter()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the center and zoom level of this MapView and triggers a redraw.
|
|
||||||
*
|
|
||||||
* @param mapPosition
|
|
||||||
* the new map position of this MapView.
|
|
||||||
*/
|
|
||||||
public void setMapCenter(MapPosition mapPosition) {
|
|
||||||
Log.d(TAG, "setMapCenter "
|
|
||||||
+ " lat: " + mapPosition.lat
|
|
||||||
+ " lon: " + mapPosition.lon);
|
|
||||||
|
|
||||||
mMapViewPosition.setMapCenter(mapPosition);
|
|
||||||
redrawMap(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the center of the MapView and triggers a redraw.
|
* Sets the center of the MapView and triggers a redraw.
|
||||||
*
|
*
|
||||||
@ -607,7 +557,7 @@ public class MapView extends RelativeLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return MapPosition
|
* @return MapViewPosition
|
||||||
*/
|
*/
|
||||||
public MapViewPosition getMapViewPosition() {
|
public MapViewPosition getMapViewPosition() {
|
||||||
return mMapViewPosition;
|
return mMapViewPosition;
|
||||||
@ -671,11 +621,10 @@ public class MapView extends RelativeLayout {
|
|||||||
return mTileManager;
|
return mTileManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return estimated visible axis aligned bounding box
|
||||||
|
*/
|
||||||
public BoundingBox getBoundingBox() {
|
public BoundingBox getBoundingBox() {
|
||||||
return mMapViewPosition.getViewBox();
|
return mMapViewPosition.getViewBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeoPoint getCenter() {
|
|
||||||
return new GeoPoint(mMapPosition.lat, mMapPosition.lon);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,30 +34,22 @@ import android.os.SystemClock;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||||
|
|
||||||
/**
|
|
||||||
* A MapPosition stores the latitude and longitude coordinate of a MapView
|
|
||||||
* together with its zoom level, rotation and tilt
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class MapViewPosition {
|
public class MapViewPosition {
|
||||||
private static final String TAG = MapViewPosition.class.getName();
|
private static final String TAG = MapViewPosition.class.getName();
|
||||||
|
|
||||||
public final static int MAX_ZOOMLEVEL = 17;
|
// needs to fit for int: 2 * 20 * Tile.TILE_SIZE
|
||||||
|
public final static int MAX_ZOOMLEVEL = 20;
|
||||||
public final static int MIN_ZOOMLEVEL = 2;
|
public final static int MIN_ZOOMLEVEL = 2;
|
||||||
public final static int MAX_END_SCALE = 8;
|
|
||||||
public final static double MAX_SCALE = ((1 << MAX_ZOOMLEVEL) * MAX_END_SCALE);
|
public final static double MAX_SCALE = (1 << MAX_ZOOMLEVEL);
|
||||||
public final static double MIN_SCALE = (1 << MIN_ZOOMLEVEL);
|
public final static double MIN_SCALE = (1 << MIN_ZOOMLEVEL);
|
||||||
|
|
||||||
// needs to fit for int: 2 * 20 * Tile.TILE_SIZE
|
|
||||||
public final static int ABS_ZOOMLEVEL = 20;
|
public final static int ABS_ZOOMLEVEL = 20;
|
||||||
|
|
||||||
private final static float MAX_ANGLE = 65;
|
private final static float MAX_ANGLE = 65;
|
||||||
|
|
||||||
private final MapView mMapView;
|
private final MapView mMapView;
|
||||||
|
|
||||||
private double mLatitude;
|
|
||||||
private double mLongitude;
|
|
||||||
|
|
||||||
private double mAbsScale;
|
private double mAbsScale;
|
||||||
private double mAbsX;
|
private double mAbsX;
|
||||||
private double mAbsY;
|
private double mAbsY;
|
||||||
@ -73,20 +65,7 @@ public class MapViewPosition {
|
|||||||
private double mCurY;
|
private double mCurY;
|
||||||
|
|
||||||
private float mRotation;
|
private float mRotation;
|
||||||
public float mTilt;
|
private float mTilt;
|
||||||
|
|
||||||
private final AnimationHandler mHandler;
|
|
||||||
|
|
||||||
MapViewPosition(MapView mapView) {
|
|
||||||
mMapView = mapView;
|
|
||||||
mLatitude = Double.NaN;
|
|
||||||
mLongitude = Double.NaN;
|
|
||||||
mRotation = 0.0f;
|
|
||||||
mTilt = 0;
|
|
||||||
mAbsScale = 1;
|
|
||||||
|
|
||||||
mHandler = new AnimationHandler(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Matrix4 mProjMatrix = new Matrix4();
|
private final Matrix4 mProjMatrix = new Matrix4();
|
||||||
private final Matrix4 mProjMatrixI = new Matrix4();
|
private final Matrix4 mProjMatrixI = new Matrix4();
|
||||||
@ -110,6 +89,29 @@ public class MapViewPosition {
|
|||||||
// scale map plane at VIEW_DISTANCE to near plane
|
// scale map plane at VIEW_DISTANCE to near plane
|
||||||
public final static float VIEW_SCALE = (VIEW_NEAR / VIEW_DISTANCE) * 0.5f;
|
public final static float VIEW_SCALE = (VIEW_NEAR / VIEW_DISTANCE) * 0.5f;
|
||||||
|
|
||||||
|
private final AnimationHandler mHandler;
|
||||||
|
|
||||||
|
MapViewPosition(MapView mapView) {
|
||||||
|
mMapView = mapView;
|
||||||
|
|
||||||
|
mAbsScale = 4;
|
||||||
|
mAbsX = 0.5;
|
||||||
|
mAbsY = 0.5;
|
||||||
|
|
||||||
|
mRotation = 0;
|
||||||
|
mTilt = 0;
|
||||||
|
|
||||||
|
updatePosition();
|
||||||
|
|
||||||
|
mHandler = new AnimationHandler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePosition() {
|
||||||
|
mCurScale = mAbsScale * Tile.TILE_SIZE;
|
||||||
|
mCurX = mAbsX * mCurScale;
|
||||||
|
mCurY = mAbsY * mCurScale;
|
||||||
|
}
|
||||||
|
|
||||||
void setViewport(int width, int height) {
|
void setViewport(int width, int height) {
|
||||||
float s = VIEW_SCALE;
|
float s = VIEW_SCALE;
|
||||||
float aspect = height / (float) width;
|
float aspect = height / (float) width;
|
||||||
@ -141,34 +143,27 @@ public class MapViewPosition {
|
|||||||
public synchronized boolean getMapPosition(MapPosition pos) {
|
public synchronized boolean getMapPosition(MapPosition pos) {
|
||||||
|
|
||||||
int z = FastMath.log2((int) mAbsScale);
|
int z = FastMath.log2((int) mAbsScale);
|
||||||
z = FastMath.clamp(z, MIN_ZOOMLEVEL, MAX_ZOOMLEVEL);
|
//z = FastMath.clamp(z, MIN_ZOOMLEVEL, MAX_ZOOMLEVEL);
|
||||||
float scale = (float) (mAbsScale / (1 << z));
|
//float scale = (float) (mAbsScale / (1 << z));
|
||||||
|
|
||||||
if (pos.lat == mLatitude
|
boolean changed = (pos.zoomLevel != z
|
||||||
&& pos.lon == mLongitude
|
|| pos.x != mAbsX
|
||||||
&& pos.zoomLevel == z
|
|| pos.y != mAbsY
|
||||||
&& pos.scale == scale
|
|| pos.scale != mAbsScale
|
||||||
&& pos.angle == mRotation
|
|| pos.angle != mRotation
|
||||||
&& pos.tilt == mTilt)
|
|| pos.tilt != mTilt);
|
||||||
return false;
|
|
||||||
|
|
||||||
pos.lat = mLatitude;
|
|
||||||
pos.lon = mLongitude;
|
|
||||||
pos.angle = mRotation;
|
pos.angle = mRotation;
|
||||||
pos.tilt = mTilt;
|
pos.tilt = mTilt;
|
||||||
|
|
||||||
pos.absX = mAbsX;
|
pos.x = mAbsX;
|
||||||
pos.absY = mAbsY;
|
pos.y = mAbsY;
|
||||||
pos.absScale = mAbsScale;
|
pos.scale = mAbsScale;
|
||||||
|
|
||||||
// for tiling
|
// for tiling
|
||||||
pos.scale = scale;
|
pos.zoomLevel = z;
|
||||||
pos.zoomLevel = (byte) z;
|
|
||||||
|
|
||||||
pos.x = mAbsX * (Tile.TILE_SIZE << z);
|
return changed;
|
||||||
pos.y = mAbsY * (Tile.TILE_SIZE << z);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -250,23 +245,8 @@ public class MapViewPosition {
|
|||||||
|
|
||||||
/** @return the current center point of the MapView. */
|
/** @return the current center point of the MapView. */
|
||||||
public synchronized GeoPoint getMapCenter() {
|
public synchronized GeoPoint getMapCenter() {
|
||||||
return new GeoPoint(mLatitude, mLongitude);
|
return new GeoPoint(MercatorProjection.toLatitude(mAbsY),
|
||||||
}
|
MercatorProjection.toLongitude(mAbsX));
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a MapPosition or null, if this map position is not valid.
|
|
||||||
* @see #isValid()
|
|
||||||
*/
|
|
||||||
public synchronized MapPosition getMapPosition() {
|
|
||||||
if (!isValid()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int z = FastMath.log2((int) mAbsScale);
|
|
||||||
z = FastMath.clamp(z, MIN_ZOOMLEVEL, MAX_ZOOMLEVEL);
|
|
||||||
float scale = (float) (mAbsScale / (1 << z));
|
|
||||||
|
|
||||||
return new MapPosition(mLatitude, mLongitude, (byte) z, scale, mRotation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -303,10 +283,10 @@ public class MapViewPosition {
|
|||||||
maxY = Math.max(maxY, dy);
|
maxY = Math.max(maxY, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
minX = MercatorProjection.toLongitude(minX, mCurScale);
|
minX = MercatorProjection.toLongitude(minX / mCurScale);
|
||||||
maxX = MercatorProjection.toLongitude(maxX, mCurScale);
|
maxX = MercatorProjection.toLongitude(maxX / mCurScale);
|
||||||
minY = MercatorProjection.toLatitude(minY, mCurScale);
|
minY = MercatorProjection.toLatitude(minY / mCurScale);
|
||||||
maxY = MercatorProjection.toLatitude(maxY, mCurScale);
|
maxY = MercatorProjection.toLatitude(maxY / mCurScale);
|
||||||
|
|
||||||
// yea, this is upside down..
|
// yea, this is upside down..
|
||||||
BoundingBox bbox = new BoundingBox(maxY, minX, minY, maxX);
|
BoundingBox bbox = new BoundingBox(maxY, minX, minY, maxX);
|
||||||
@ -446,27 +426,6 @@ public class MapViewPosition {
|
|||||||
mUnprojMatrix.multiplyMM(mTmpMatrix, mProjMatrixI);
|
mUnprojMatrix.multiplyMM(mTmpMatrix, mProjMatrixI);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if this MapViewPosition is valid, false otherwise. */
|
|
||||||
public synchronized boolean isValid() {
|
|
||||||
if (Double.isNaN(mLatitude)) {
|
|
||||||
return false;
|
|
||||||
} else if (mLatitude < MercatorProjection.LATITUDE_MIN) {
|
|
||||||
return false;
|
|
||||||
} else if (mLatitude > MercatorProjection.LATITUDE_MAX) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Double.isNaN(mLongitude)) {
|
|
||||||
return false;
|
|
||||||
} else if (mLongitude < MercatorProjection.LONGITUDE_MIN) {
|
|
||||||
return false;
|
|
||||||
} else if (mLongitude > MercatorProjection.LONGITUDE_MAX) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves this MapViewPosition by the given amount of pixels.
|
* Moves this MapViewPosition by the given amount of pixels.
|
||||||
*
|
*
|
||||||
@ -495,9 +454,6 @@ public class MapViewPosition {
|
|||||||
while (mAbsX < 0)
|
while (mAbsX < 0)
|
||||||
mAbsX += 1;
|
mAbsX += 1;
|
||||||
|
|
||||||
mLongitude = MercatorProjection.toLongitude(mAbsX);
|
|
||||||
mLatitude = MercatorProjection.toLatitude(mAbsY);
|
|
||||||
|
|
||||||
updatePosition();
|
updatePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,9 +472,6 @@ public class MapViewPosition {
|
|||||||
while (mAbsX < 0)
|
while (mAbsX < 0)
|
||||||
mAbsX += 1;
|
mAbsX += 1;
|
||||||
|
|
||||||
mLongitude = MercatorProjection.toLongitude(mAbsX);
|
|
||||||
mLatitude = MercatorProjection.toLatitude(mAbsY);
|
|
||||||
|
|
||||||
updatePosition();
|
updatePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -615,25 +568,26 @@ public class MapViewPosition {
|
|||||||
updateMatrix();
|
updateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized float getTilt() {
|
||||||
|
return mTilt;
|
||||||
|
}
|
||||||
|
|
||||||
private void setMapCenter(double latitude, double longitude) {
|
private void setMapCenter(double latitude, double longitude) {
|
||||||
mLatitude = MercatorProjection.limitLatitude(latitude);
|
latitude = MercatorProjection.limitLatitude(latitude);
|
||||||
mLongitude = MercatorProjection.limitLongitude(longitude);
|
longitude = MercatorProjection.limitLongitude(longitude);
|
||||||
mAbsX = MercatorProjection.longitudeToX(mLongitude);
|
mAbsX = MercatorProjection.longitudeToX(longitude);
|
||||||
mAbsY = MercatorProjection.latitudeToY(mLatitude);
|
mAbsY = MercatorProjection.latitudeToY(latitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized void setMapPosition(MapPosition mapPosition) {
|
||||||
|
setZoomLevelLimit(mapPosition.zoomLevel);
|
||||||
|
mAbsX = mapPosition.x;
|
||||||
|
mAbsY = mapPosition.y;
|
||||||
updatePosition();
|
updatePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void setMapCenter(GeoPoint geoPoint) {
|
synchronized void setMapCenter(GeoPoint geoPoint) {
|
||||||
setMapCenter(geoPoint.getLatitude(), geoPoint.getLongitude());
|
setMapCenter(geoPoint.getLatitude(), geoPoint.getLongitude());
|
||||||
}
|
|
||||||
|
|
||||||
synchronized void setMapCenter(MapPosition mapPosition) {
|
|
||||||
setZoomLevelLimit(mapPosition.zoomLevel);
|
|
||||||
setMapCenter(mapPosition.lat, mapPosition.lon);
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized void setZoomLevel(byte zoomLevel) {
|
|
||||||
setZoomLevelLimit(zoomLevel);
|
|
||||||
updatePosition();
|
updatePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,13 +595,6 @@ public class MapViewPosition {
|
|||||||
mAbsScale = FastMath.clamp(1 << zoomLevel, MIN_SCALE, MAX_SCALE);
|
mAbsScale = FastMath.clamp(1 << zoomLevel, MIN_SCALE, MAX_SCALE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePosition() {
|
|
||||||
mCurScale = mAbsScale * Tile.TILE_SIZE;
|
|
||||||
|
|
||||||
mCurX = mAbsX * mCurScale;
|
|
||||||
mCurY = mAbsY * mCurScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
// TODO move to MapAnimator:
|
// TODO move to MapAnimator:
|
||||||
|
|
||||||
|
|||||||
@ -78,7 +78,7 @@ final class TouchHandler implements OnGestureListener, OnDoubleTapListener {
|
|||||||
*/
|
*/
|
||||||
public TouchHandler(Context context, MapView mapView) {
|
public TouchHandler(Context context, MapView mapView) {
|
||||||
mMapView = mapView;
|
mMapView = mapView;
|
||||||
mMapPosition = mapView.getMapPosition();
|
mMapPosition = mapView.getMapViewPosition();
|
||||||
mOverlayManager = mapView.getOverlayManager();
|
mOverlayManager = mapView.getOverlayManager();
|
||||||
mGestureDetector = new GestureDetector(context, this);
|
mGestureDetector = new GestureDetector(context, this);
|
||||||
mGestureDetector.setOnDoubleTapListener(this);
|
mGestureDetector.setOnDoubleTapListener(this);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user