change max zoom-level to 24
- fix bug in ScanBox where tiles where not visible when map rotation had a steep angle - refactor ScanBox, add transScale utility
This commit is contained in:
parent
8a808265a5
commit
24438c1e68
@ -310,24 +310,19 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
// lock tiles while updating isVisible state
|
||||
synchronized (GLRenderer.tilelock) {
|
||||
int tileZoom = tiles[0].zoomLevel;
|
||||
|
||||
for (int i = 0; i < mDrawTiles.cnt; i++)
|
||||
tiles[i].isVisible = false;
|
||||
|
||||
int z = tiles[0].zoomLevel;
|
||||
|
||||
double curScale = Tile.SIZE * pos.scale;
|
||||
double tileScale = Tile.SIZE * (pos.scale / (1 << z));
|
||||
|
||||
for (int i = 0; i < 8; i += 2) {
|
||||
coords[i + 0] = (float) ((pos.x * curScale + coords[i + 0]) / tileScale);
|
||||
coords[i + 1] = (float) ((pos.y * curScale + coords[i + 1]) / tileScale);
|
||||
}
|
||||
// scale and translate projection to tile coordinates
|
||||
ScanBox.transScale(pos.x, pos.y, pos.scale, tileZoom, coords);
|
||||
|
||||
// count placeholder tiles
|
||||
mNumTileHolder = 0;
|
||||
|
||||
// check visibile tiles
|
||||
mScanBox.scan(coords, z);
|
||||
mScanBox.scan(coords, tileZoom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -15,8 +15,37 @@
|
||||
|
||||
package org.oscim.renderer;
|
||||
|
||||
import org.oscim.core.Tile;
|
||||
|
||||
/**
|
||||
* ScanBox is used to calculate tile coordinates that intersect
|
||||
* the box (or trapezoid) which is usually the projection of
|
||||
* screen bounds to the map at a given zoom-level.
|
||||
*
|
||||
* use:
|
||||
* MapViewPosition.getMapViewProjection(coords)
|
||||
* ScanBox.transScale(pos.x, pos.y, pos.scale, zoomLevel, coords)
|
||||
* yourScanBox.scan(coords, zoomLevel);
|
||||
*
|
||||
* where zoomLevel is the zoom-level for which tile coordinates
|
||||
* should be calculated.
|
||||
* */
|
||||
public abstract class ScanBox {
|
||||
|
||||
public static void transScale(double x, double y, double scale, int zoom, float[] box){
|
||||
scale *= Tile.SIZE;
|
||||
|
||||
//double curScale = Tile.SIZE * scale;
|
||||
double div = scale / (1 << zoom);
|
||||
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
|
||||
for (int i = 0; i < 8; i += 2) {
|
||||
box[i + 0] = (float) ((x + box[i + 0]) / div);
|
||||
box[i + 1] = (float) ((y + box[i + 1]) / div);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* ported from Polymaps: Layer.js
|
||||
*/
|
||||
@ -44,7 +73,7 @@ public abstract class ScanBox {
|
||||
private Edge ab = new Edge();
|
||||
private Edge bc = new Edge();
|
||||
private Edge ca = new Edge();
|
||||
private float minX, maxX;
|
||||
private int minX, maxX;
|
||||
|
||||
protected int mZoom;
|
||||
|
||||
@ -53,18 +82,27 @@ public abstract class ScanBox {
|
||||
public void scan(float[] coords, int zoom) {
|
||||
mZoom = zoom;
|
||||
|
||||
maxX = Float.MIN_VALUE;
|
||||
minX = Float.MAX_VALUE;
|
||||
|
||||
// clip result to min/max as steep angles
|
||||
// cause overshooting in x direction.
|
||||
float max = Float.MIN_VALUE;
|
||||
float min = Float.MAX_VALUE;
|
||||
|
||||
for(int i = 0; i < 8; i += 2){
|
||||
float x = coords[i];
|
||||
if (x > maxX)
|
||||
maxX = x;
|
||||
if (x < minX)
|
||||
minX = x;
|
||||
if (x > max)
|
||||
max = x;
|
||||
if (x < min)
|
||||
min = x;
|
||||
}
|
||||
maxX = (float)Math.ceil(maxX);
|
||||
minX = (float)Math.floor(minX);
|
||||
|
||||
max = (float)Math.ceil(max);
|
||||
min = (float)Math.floor(min);
|
||||
if (min == max)
|
||||
max++;
|
||||
|
||||
minX = (int) min;
|
||||
maxX = (int) max;
|
||||
|
||||
// top-left -> top-right
|
||||
ab.set(coords[0], coords[1], coords[2], coords[3]);
|
||||
@ -108,10 +146,10 @@ public abstract class ScanBox {
|
||||
if (ca.dy == 0)
|
||||
return;
|
||||
|
||||
if (ab.dy > 0.1)
|
||||
if (ab.dy > 0.0)
|
||||
scanSpans(ca, ab);
|
||||
|
||||
if (bc.dy > 0.1)
|
||||
if (bc.dy > 0.0)
|
||||
scanSpans(ca, bc);
|
||||
}
|
||||
|
||||
@ -152,13 +190,13 @@ public abstract class ScanBox {
|
||||
if (dy > e0.dy)
|
||||
dy = e0.dy;
|
||||
|
||||
float x0 = (float)Math.ceil(e0.x0 + m0 * dy);
|
||||
int x0 = (int)Math.ceil(e0.x0 + m0 * dy);
|
||||
|
||||
dy = d1 + y - e1.y0;
|
||||
if (dy > e1.dy)
|
||||
dy = e1.dy;
|
||||
|
||||
float x1 = (float)Math.floor(e1.x0 + m1 * dy);
|
||||
int x1 = (int)Math.floor(e1.x0 + m1 * dy);
|
||||
|
||||
if (x1 < minX)
|
||||
x1 = minX;
|
||||
@ -167,7 +205,7 @@ public abstract class ScanBox {
|
||||
x0 = maxX;
|
||||
|
||||
if (x1 < x0)
|
||||
setVisible(y, (int) x1, (int) x0);
|
||||
setVisible(y, x1, x0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,8 +113,8 @@ public class TileManager {
|
||||
clearTile(mTiles[i]);
|
||||
}
|
||||
//else {
|
||||
// mInitialized is set when surface changed
|
||||
// and VBOs might be lost
|
||||
// mInitialized is set when surface changed
|
||||
// and VBOs might be lost
|
||||
// VertexPool.init();
|
||||
//}
|
||||
|
||||
@ -162,26 +162,21 @@ public class TileManager {
|
||||
// jobs come in.
|
||||
mMapView.addJobs(null);
|
||||
|
||||
// scale and translate projection to tile coordinates
|
||||
// load some tiles more than currently visible (* 0.75)
|
||||
double scale = pos.scale * 0.9f;
|
||||
double curScale = Tile.SIZE * scale;
|
||||
int zoomLevel = FastMath.clamp(pos.zoomLevel, MIN_ZOOMLEVEL, MAX_ZOOMLEVEL);
|
||||
|
||||
double tileScale = Tile.SIZE * (scale / (1 << zoomLevel));
|
||||
int tileZoom = FastMath.clamp(pos.zoomLevel, MIN_ZOOMLEVEL, MAX_ZOOMLEVEL);
|
||||
|
||||
float[] coords = mTileCoords;
|
||||
mMapViewPosition.getMapViewProjection(coords);
|
||||
|
||||
for (int i = 0; i < 8; i += 2) {
|
||||
coords[i + 0] = (float) ((pos.x * curScale + coords[i + 0]) / tileScale);
|
||||
coords[i + 1] = (float) ((pos.y * curScale + coords[i + 1]) / tileScale);
|
||||
}
|
||||
// scale and translate projection to tile coordinates
|
||||
ScanBox.transScale(pos.x, pos.y, scale, tileZoom, coords);
|
||||
|
||||
// scan visible tiles. callback function calls 'addTile'
|
||||
// which sets mNewTiles
|
||||
mNewTiles.cnt = 0;
|
||||
mScanBox.scan(coords, zoomLevel);
|
||||
mScanBox.scan(coords, tileZoom);
|
||||
|
||||
MapTile[] newTiles = mNewTiles.tiles;
|
||||
MapTile[] curTiles = mCurrentTiles.tiles;
|
||||
@ -562,22 +557,22 @@ public class TileManager {
|
||||
}
|
||||
|
||||
private final ScanBox mScanBox = new ScanBox() {
|
||||
|
||||
@Override
|
||||
public void setVisible(int y, int x1, int x2) {
|
||||
MapTile[] tiles = mNewTiles.tiles;
|
||||
int cnt = mNewTiles.cnt;
|
||||
int max = tiles.length;
|
||||
int maxTiles = tiles.length;
|
||||
|
||||
int xmax = 1 << mZoom;
|
||||
|
||||
for (int x = x1; x < x2; x++) {
|
||||
MapTile tile = null;
|
||||
|
||||
if (cnt == max) {
|
||||
Log.d(TAG, "reached maximum tiles " + max);
|
||||
if (cnt == maxTiles) {
|
||||
Log.d(TAG, "reached maximum tiles " + maxTiles);
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE to myself: do not modify x!
|
||||
int xx = x;
|
||||
|
||||
if (x < 0 || x >= xmax) {
|
||||
|
||||
@ -38,13 +38,14 @@ public class MapViewPosition {
|
||||
private static final String TAG = MapViewPosition.class.getName();
|
||||
|
||||
// needs to fit for int: 2 * 20 * Tile.SIZE
|
||||
public final static int MAX_ZOOMLEVEL = 20;
|
||||
public final static int MAX_ZOOMLEVEL = 24;
|
||||
public final static int MIN_ZOOMLEVEL = 2;
|
||||
|
||||
public final static double MAX_SCALE = (1 << MAX_ZOOMLEVEL);
|
||||
public final static double MIN_SCALE = (1 << MIN_ZOOMLEVEL);
|
||||
|
||||
public final static int ABS_ZOOMLEVEL = 20;
|
||||
// TODO: remove. only used for animations
|
||||
public final static int ABS_ZOOMLEVEL = 22;
|
||||
|
||||
private final static float MAX_ANGLE = 65;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user