diff --git a/src/org/oscim/renderer/GLRenderer.java b/src/org/oscim/renderer/GLRenderer.java index 6fd68e9a..cae9d1c7 100644 --- a/src/org/oscim/renderer/GLRenderer.java +++ b/src/org/oscim/renderer/GLRenderer.java @@ -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); } } diff --git a/src/org/oscim/renderer/ScanBox.java b/src/org/oscim/renderer/ScanBox.java index 086ad7f2..6b7125e8 100644 --- a/src/org/oscim/renderer/ScanBox.java +++ b/src/org/oscim/renderer/ScanBox.java @@ -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); } } } diff --git a/src/org/oscim/renderer/TileManager.java b/src/org/oscim/renderer/TileManager.java index e7340367..70a1b642 100644 --- a/src/org/oscim/renderer/TileManager.java +++ b/src/org/oscim/renderer/TileManager.java @@ -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) { diff --git a/src/org/oscim/view/MapViewPosition.java b/src/org/oscim/view/MapViewPosition.java index 93ce66a6..2dd781ad 100644 --- a/src/org/oscim/view/MapViewPosition.java +++ b/src/org/oscim/view/MapViewPosition.java @@ -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;