diff --git a/res/menu/options_menu.xml b/res/menu/options_menu.xml
index 965415e5..c525f985 100644
--- a/res/menu/options_menu.xml
+++ b/res/menu/options_menu.xml
@@ -22,6 +22,10 @@
+
+
+
+
-
-
+
- OpenScienceMap
@@ -51,6 +51,7 @@
About this software
Map file
Position
+ Enable rotation
Enter coordinates
Last known location
Map file center
diff --git a/src/org/mapsforge/android/MapView.java b/src/org/mapsforge/android/MapView.java
index 621fba71..11c71f00 100644
--- a/src/org/mapsforge/android/MapView.java
+++ b/src/org/mapsforge/android/MapView.java
@@ -24,11 +24,11 @@ import javax.xml.parsers.ParserConfigurationException;
import org.mapsforge.android.mapgenerator.IMapGenerator;
import org.mapsforge.android.mapgenerator.JobQueue;
+import org.mapsforge.android.mapgenerator.JobTile;
import org.mapsforge.android.mapgenerator.MapDatabaseFactory;
import org.mapsforge.android.mapgenerator.MapDatabases;
import org.mapsforge.android.mapgenerator.MapRendererFactory;
import org.mapsforge.android.mapgenerator.MapRenderers;
-import org.mapsforge.android.mapgenerator.JobTile;
import org.mapsforge.android.mapgenerator.MapWorker;
import org.mapsforge.android.mapgenerator.Theme;
import org.mapsforge.android.rendertheme.ExternalRenderTheme;
@@ -78,6 +78,7 @@ public class MapView extends GLSurfaceView {
private static final Byte DEFAULT_START_ZOOM_LEVEL = Byte.valueOf((byte) 16);
public final static boolean debugFrameTime = false;
+ public boolean enableRotation = false;
private final MapController mMapController;
private final MapViewPosition mMapViewPosition;
@@ -160,7 +161,7 @@ public class MapView extends GLSurfaceView {
IMapDatabase mapDatabase;
if (mDebugDatabase) {
mapDatabase = MapDatabaseFactory
- .createMapDatabase(MapDatabases.JSON_READER);
+ .createMapDatabase(MapDatabases.TEST_READER);
} else {
mapDatabase = MapDatabaseFactory.createMapDatabase(mapDatabaseType);
}
@@ -684,6 +685,10 @@ public class MapView extends GLSurfaceView {
mapWorker.proceed();
}
+ public void enableRotation(boolean enable) {
+ enableRotation = enable;
+ }
+
// public final int
// public Handler messageHandler = new Handler() {
//
diff --git a/src/org/mapsforge/android/MapViewPosition.java b/src/org/mapsforge/android/MapViewPosition.java
index 4c76701e..e8f650eb 100644
--- a/src/org/mapsforge/android/MapViewPosition.java
+++ b/src/org/mapsforge/android/MapViewPosition.java
@@ -19,7 +19,6 @@ import org.mapsforge.core.MapPosition;
import org.mapsforge.core.MercatorProjection;
import android.util.FloatMath;
-import android.util.Log;
/**
* A MapPosition stores the latitude and longitude coordinate of a MapView together with its zoom level.
@@ -112,41 +111,35 @@ public class MapViewPosition {
public synchronized void moveMap(float mx, float my) {
double pixelX = MercatorProjection.longitudeToPixelX(mLongitude, mZoomLevel);
double pixelY = MercatorProjection.latitudeToPixelY(mLatitude, mZoomLevel);
+ double dx, dy;
- // float rad = (float) Math.toRadians(mRotation);
- // mx /= mScale;
- // my /= mScale;
- //
- // double x = mx * FloatMath.cos(rad) + my * -FloatMath.sin(rad);
- // double y = mx * FloatMath.sin(rad) + my * FloatMath.cos(rad);
- //
- // double dx = pixelX - x;
- // double dy = pixelY - y;
+ if (mMapView.enableRotation) {
+ float rad = (float) Math.toRadians(mRotation);
+ dx = mx / mScale;
+ dy = my / mScale;
- double dx = pixelX - mx / mScale;
- double dy = pixelY - my / mScale;
+ double x = dx * FloatMath.cos(rad) + dy * -FloatMath.sin(rad);
+ double y = dx * FloatMath.sin(rad) + dy * FloatMath.cos(rad);
+ dx = pixelX - x;
+ dy = pixelY - y;
+ }
+ else {
+ dx = pixelX - mx / mScale;
+ dy = pixelY - my / mScale;
+ }
mLatitude = MercatorProjection.pixelYToLatitude(dy, mZoomLevel);
mLatitude = MercatorProjection.limitLatitude(mLatitude);
mLongitude = MercatorProjection.pixelXToLongitude(dx, mZoomLevel);
- //
- // mLatitude = MercatorProjection.pixelYToLatitude(pixelY - moveVertical / mScale,
- // mZoomLevel);
- // mLatitude = MercatorProjection.limitLatitude(mLatitude);
- //
- // mLongitude = MercatorProjection.pixelXToLongitude(pixelX - moveHorizontal
- // / mScale, mZoomLevel);
-
mLongitude = MercatorProjection.wrapLongitude(mLongitude);
// mLongitude = MercatorProjection.limitLongitude(mLongitude);
}
- public synchronized void rotateMap(float angle) {
+ public synchronized void rotateMap(float angle, float cx, float cy) {
+ moveMap(cx, cy);
mRotation -= angle;
- Log.d("...", "angle:" + mRotation);
- // mRotation %= 360;
}
synchronized void setMapCenter(GeoPoint geoPoint) {
diff --git a/src/org/mapsforge/android/TouchHandler.java b/src/org/mapsforge/android/TouchHandler.java
index ce40e210..53b869a3 100644
--- a/src/org/mapsforge/android/TouchHandler.java
+++ b/src/org/mapsforge/android/TouchHandler.java
@@ -112,16 +112,33 @@ public class TouchHandler {
return true;
}
- // if (multi > 0) {
- // double dx = event.getX(0) - event.getX(1);
- // double dy = event.getY(0) - event.getY(1);
- // double rad = Math.atan2(dy, dx);
- // float angle = (float) Math.toDegrees(rad);
- // mMapPosition.rotateMap(angle - mAngle);
- // mAngle = angle;
- // mMapView.redrawTiles();
- // }
+ if (mMapView.enableRotation) {
+ if (multi > 0) {
+ double x1 = event.getX(0);
+ double x2 = event.getX(1);
+ double y1 = event.getY(0);
+ double y2 = event.getY(1);
+ double dx = x1 - x2;
+ double dy = y1 - y2;
+
+ double rad = Math.atan2(dy, dx);
+ float angle = (float) Math.toDegrees(rad);
+
+ // focus point relative to center
+ double cx = (mMapView.getWidth() >> 1) - (x1 + x2) / 2;
+ double cy = (mMapView.getHeight() >> 1) - (y1 + y2) / 2;
+ double r = Math.toRadians(angle - mAngle);
+
+ double x = cx * Math.cos(r) + cy * -Math.sin(r) - cx;
+ double y = cx * Math.sin(r) + cy * Math.cos(r) - cy;
+ // Log.d("...", "move " + x + " " + y + " " + cx + " " + cy);
+
+ mMapPosition.rotateMap(angle - mAngle, (float) x, (float) y);
+ mAngle = angle;
+ mMapView.redrawTiles();
+ }
+ }
// save the position of the event
mPosX = event.getX(pointerIndex);
mPosY = event.getY(pointerIndex);
@@ -182,7 +199,7 @@ public class TouchHandler {
private boolean onActionUp(MotionEvent motionEvent) {
mActivePointerId = INVALID_POINTER_ID;
mScaling = false;
-
+ multi = 0;
return true;
}
@@ -400,7 +417,11 @@ public class TouchHandler {
mCenterX = mMapView.getWidth() >> 1;
mCenterY = mMapView.getHeight() >> 1;
mScale = 1;
- // mMapPosition = mMapView.getMapPosition();
+
+ if (mTimer != null) {
+ mTimer.cancel();
+ mTimer = null;
+ }
return true;
}
diff --git a/src/org/mapsforge/android/glrenderer/MapGenerator.java b/src/org/mapsforge/android/glrenderer/MapGenerator.java
index b448c69a..ff9cdcf7 100644
--- a/src/org/mapsforge/android/glrenderer/MapGenerator.java
+++ b/src/org/mapsforge/android/glrenderer/MapGenerator.java
@@ -428,12 +428,11 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mDebugDrawUnmatched = debugSettings.mDrawUnmatchted;
// fixed now....
- if (tile.newData || tile.isReady || tile.isCanceled) {
+ if (tile.newData || tile.isReady) {
Log.d(TAG, "XXX tile already loaded "
+ tile + " "
+ tile.newData + " "
- + tile.isReady + " "
- + tile.isCanceled);
+ + tile.isReady + " ");
return false;
}
diff --git a/src/org/mapsforge/android/glrenderer/MapRenderer.java b/src/org/mapsforge/android/glrenderer/MapRenderer.java
index d877a706..073dadfe 100644
--- a/src/org/mapsforge/android/glrenderer/MapRenderer.java
+++ b/src/org/mapsforge/android/glrenderer/MapRenderer.java
@@ -36,7 +36,6 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.util.ArrayList;
-import java.util.Collections;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
@@ -47,7 +46,6 @@ import org.mapsforge.android.mapgenerator.JobTile;
import org.mapsforge.android.rendertheme.RenderTheme;
import org.mapsforge.android.utils.GlUtils;
import org.mapsforge.core.MapPosition;
-import org.mapsforge.core.MercatorProjection;
import org.mapsforge.core.Tile;
import android.opengl.GLES20;
@@ -57,45 +55,11 @@ import android.util.FloatMath;
import android.util.Log;
public class MapRenderer implements org.mapsforge.android.IMapRenderer {
- private static final String TAG = "MapRenderer";
- private static final int MB = 1024 * 1024;
- private static final int SHORT_BYTES = 2;
- static final float COORD_MULTIPLIER = 8.0f;
-
- private static final int MAX_TILES_IN_QUEUE = 40;
- private static final int CACHE_TILES_MAX = 250;
- private static final int LIMIT_BUFFERS = 16 * MB;
-
- private static int CACHE_TILES = CACHE_TILES_MAX;
-
- private final MapView mMapView;
- private static ArrayList mJobList;
- private static ArrayList mVBOs;
-
- // all tiles currently referenced
- private static ArrayList mTiles;
-
- // tiles that have new data to upload, see passTile()
- private static ArrayList mTilesLoaded;
-
- private static int mWidth, mHeight;
- private static float mAspect;
-
- // current center tile, values used to check if position has
- // changed for updating current tile list
- private static long mTileX, mTileY;
- private static float mPrevScale;
- private static byte mPrevZoom;
-
- private static int rotateBuffers = 2;
- private static ShortBuffer shortBuffer[];
- private static short[] mFillCoords;
-
- // bytes currently loaded in VBOs
- private static int mBufferMemoryUsage;
-
- class TilesData {
+ /**
+ * used for passing tiles to be rendered from TileLoader(Main) to GLThread
+ */
+ static class TilesData {
int cnt = 0;
final MapTile[] tiles;
@@ -104,14 +68,39 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
}
+ private static final String TAG = "MapRenderer";
+
+ private static final int MB = 1024 * 1024;
+ private static final int SHORT_BYTES = 2;
+ static final float COORD_MULTIPLIER = 8.0f;
+
+ private static final int CACHE_TILES_MAX = 200;
+ private static final int LIMIT_BUFFERS = 16 * MB;
+
+ private static int CACHE_TILES = CACHE_TILES_MAX;
+
+ private final MapView mMapView;
+ private static ArrayList mVBOs;
+
+ private static int mWidth, mHeight;
+ private static float mAspect;
+
+ private static int rotateBuffers = 2;
+ private static ShortBuffer shortBuffer[];
+ private static short[] mFillCoords;
+
+ // bytes currently loaded in VBOs
+ private static int mBufferMemoryUsage;
+
private static float[] mMVPMatrix = new float[16];
- // private static float[] mRotateMatrix = new float[16];
- // private static float[] mProjMatrix = new float[16];
+ private static float[] mRotateMatrix = new float[16];
+ private static float[] mProjMatrix = new float[16];
+ private static float[] mRotTMatrix = new float[16];
// newTiles is set in updateVisibleList and swapped
// with curTiles on main thread. curTiles is swapped
// with drawTiles in onDrawFrame in GL thread.
- private static TilesData newTiles, curTiles, drawTiles;
+ private static TilesData curTiles, drawTiles;
// draw position is updated from current position in onDrawFrame
// keeping the position and active tiles consistent while drawing
@@ -121,8 +110,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// changed. used in onDrawFrame to flip curTiles/drawTiles
private static boolean mUpdateTiles;
- private static boolean mInitial;
-
private float[] mClearColor = null;
// number of tiles drawn in one frame
@@ -130,6 +117,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private static boolean mUpdateColor = false;
+ static Object lock = new Object();
+
/**
* @param mapView
* the MapView
@@ -138,475 +127,52 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
Log.d(TAG, "init MapRenderer");
mMapView = mapView;
-
- if (mInitial)
- return;
-
- mJobList = new ArrayList();
- mTiles = new ArrayList();
- mTilesLoaded = new ArrayList(30);
-
Matrix.setIdentityM(mMVPMatrix, 0);
- mInitial = true;
mUpdateTiles = false;
-
- QuadTree.init();
- }
-
- private static int updateTileDistances(ArrayList> tiles,
- MapPosition mapPosition) {
- int h = (Tile.TILE_SIZE >> 1);
- byte zoom = mapPosition.zoomLevel;
- long x = (long) mapPosition.x;
- long y = (long) mapPosition.y;
-
- int diff;
- long dx, dy;
- int cnt = 0;
-
- // TODO this could need some fixing, and optimization
- // to consider move/zoom direction
-
- for (int i = 0, n = tiles.size(); i < n; i++) {
- JobTile t = (JobTile) tiles.get(i);
- diff = (t.zoomLevel - zoom);
- if (t.isActive)
- cnt++;
-
- if (diff == 0) {
- dx = (t.pixelX + h) - x;
- dy = (t.pixelY + h) - y;
- // t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) * 0.25f;
- t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * 0.25f;
- } else if (diff > 0) {
- // tile zoom level is child of current
-
- if (diff < 3) {
- dx = ((t.pixelX + h) >> diff) - x;
- dy = ((t.pixelY + h) >> diff) - y;
- }
- else {
- dx = ((t.pixelX + h) >> (diff >> 1)) - x;
- dy = ((t.pixelY + h) >> (diff >> 1)) - y;
- }
- // t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy));
- t.distance = FloatMath.sqrt((dx * dx + dy * dy));
-
- } else {
- // tile zoom level is parent of current
- dx = ((t.pixelX + h) << -diff) - x;
- dy = ((t.pixelY + h) << -diff) - y;
-
- // t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) * (-diff * 0.5f);
- t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * (-diff * 0.5f);
- }
- }
- return cnt;
- }
-
- private static boolean childIsActive(MapTile t) {
- MapTile c = null;
-
- for (int i = 0; i < 4; i++) {
- if (t.rel.child[i] == null)
- continue;
-
- c = t.rel.child[i].tile;
- if (c != null && c.isActive && !(c.isReady || c.newData))
- return true;
- }
-
- return false;
- }
-
- // FIXME still the chance that one jumped two zoomlevels between
- // cur and draw. should use reference counter instead
- private static boolean tileInUse(MapTile t) {
- byte z = mPrevZoom;
-
- if (t.isActive) {
- return true;
-
- } else if (t.zoomLevel == z + 1) {
- MapTile p = t.rel.parent.tile;
-
- if (p != null && p.isActive && !(p.isReady || p.newData))
- return true;
-
- } else if (t.zoomLevel == z + 2) {
- MapTile p = t.rel.parent.parent.tile;
-
- if (p != null && p.isActive && !(p.isReady || p.newData))
- return true;
-
- } else if (t.zoomLevel == z - 1) {
- if (childIsActive(t))
- return true;
-
- } else if (t.zoomLevel == z - 2) {
- for (QuadTree c : t.rel.child) {
- if (c == null)
- continue;
-
- if (c.tile != null && childIsActive(c.tile))
- return true;
- }
- } else if (t.zoomLevel == z - 3) {
- for (QuadTree c : t.rel.child) {
- if (c == null)
- continue;
-
- for (QuadTree c2 : c.child) {
- if (c2 == null)
- continue;
-
- if (c2.tile != null && childIsActive(c2.tile))
- return true;
- }
- }
- }
- return false;
- }
-
- private static void limitCache(MapPosition mapPosition, int remove) {
- int removes = remove;
-
- int size = mTiles.size();
-
- // remove orphaned tiles
- for (int i = 0; i < size;) {
- MapTile cur = mTiles.get(i);
- // make sure tile cannot be used by GL or MapWorker Thread
- if ((!cur.isActive) && (!cur.isLoading) && (!cur.newData)
- && (!cur.isReady) && (!tileInUse(cur))) {
-
- clearTile(cur);
- mTiles.remove(i);
- removes--;
- size--;
- // Log.d(TAG, "remove empty tile" + cur);
- continue;
- }
- i++;
- }
-
- if (removes <= 0)
- return;
-
- updateTileDistances(mTiles, mapPosition);
-
- Log.d(TAG, "remove tiles: " + removes);
-
- // boolean printAll = false;
-
- for (int i = 1; i <= removes; i++) {
-
- MapTile t = mTiles.get(0);
- int pos = 0;
-
- for (int j = 1; j < size; j++) {
- MapTile t2 = mTiles.get(j);
- if (t2.distance > t.distance) {
- t = t2;
- pos = j;
- }
- }
-
- synchronized (t) {
- if (t.isActive) {
- // dont remove tile used by renderthread or mapgenerator
- Log.d(TAG, "X not removing active " + t + " " + t.distance);
-
- // if (printAll) {
- // printAll = false;
- // for (GLMapTile tt : mTiles)
- // Log.d(TAG, ">>>" + tt + " " + tt.distance);
- // }
- } else if ((t.isReady || t.newData) && tileInUse(t)) {
- // check if this tile could be used as proxy
- // for not yet drawn active tile
- Log.d(TAG, "X not removing proxy: " + t + " " + t.distance);
- } else {
- if (t.isLoading) {
- Log.d(TAG, ">>> cancel loading " + t + " " + t.distance);
- t.isCanceled = true;
- }
- mTiles.remove(pos);
- clearTile(t);
- size--;
- }
- }
- }
- }
-
- private static void limitLoadQueue(int remove) {
- int size = remove;
-
- synchronized (mTilesLoaded) {
-
- // remove uploaded tiles
- for (int i = 0; i < size;) {
- MapTile t = mTilesLoaded.get(i);
- // rel == null means tile is already removed by limitCache
- if (!t.newData || t.rel == null) {
- mTilesLoaded.remove(i);
- size--;
- continue;
- }
- i++;
- }
-
- // clear loaded but not used tiles
- if (size < MAX_TILES_IN_QUEUE)
- return;
-
- while (size-- > MAX_TILES_IN_QUEUE - 20) {
- MapTile t = mTilesLoaded.get(size);
-
- synchronized (t) {
- if (t.rel == null) {
- mTilesLoaded.remove(size);
- continue;
- }
-
- if (tileInUse(t)) {
- // Log.d(TAG, "keep unused tile data: " + t + " " + t.isActive);
- continue;
- }
-
- mTilesLoaded.remove(size);
- mTiles.remove(t);
- // Log.d(TAG, "remove unused tile data: " + t);
- clearTile(t);
- }
- }
- }
- }
-
- private boolean updateVisibleList(MapPosition mapPosition, int zdir) {
- double x = mapPosition.x;
- double y = mapPosition.y;
- byte zoomLevel = mapPosition.zoomLevel;
- float scale = mapPosition.scale;
-
- double add = 1.0f / scale;
- int offsetX = (int) ((mWidth >> 1) * add) + Tile.TILE_SIZE;
- int offsetY = (int) ((mHeight >> 1) * add) + Tile.TILE_SIZE;
-
- long pixelRight = (long) x + offsetX;
- long pixelBottom = (long) y + offsetY;
- long pixelLeft = (long) x - offsetX;
- long pixelTop = (long) y - offsetY;
-
- int tileLeft = MercatorProjection.pixelXToTileX(pixelLeft, zoomLevel);
- int tileTop = MercatorProjection.pixelYToTileY(pixelTop, zoomLevel);
- int tileRight = MercatorProjection.pixelXToTileX(pixelRight, zoomLevel);
- int tileBottom = MercatorProjection.pixelYToTileY(pixelBottom, zoomLevel);
-
- mJobList.clear();
- mMapView.addJobs(null);
-
- int tiles = 0;
- if (newTiles == null)
- return false;
-
- int max = newTiles.tiles.length - 1;
-
- for (int yy = tileTop; yy <= tileBottom; yy++) {
- for (int xx = tileLeft; xx <= tileRight; xx++) {
-
- if (tiles == max)
- break;
-
- MapTile tile = QuadTree.getTile(xx, yy, zoomLevel);
-
- if (tile == null) {
- tile = new MapTile(xx, yy, zoomLevel);
-
- QuadTree.add(tile);
- mTiles.add(tile);
- }
-
- newTiles.tiles[tiles++] = tile;
-
- if (!(tile.isLoading || tile.newData || tile.isReady)) {
- mJobList.add(tile);
- }
-
- if (zdir > 0 && zoomLevel > 0) {
- // prefetch parent
- MapTile parent = tile.rel.parent.tile;
-
- if (parent == null) {
- parent = new MapTile(xx >> 1, yy >> 1, (byte) (zoomLevel - 1));
-
- QuadTree.add(parent);
- mTiles.add(parent);
- }
-
- if (!(parent.isLoading || parent.isReady || parent.newData)) {
- if (!mJobList.contains(parent))
- mJobList.add(parent);
- }
- }
- }
- }
-
- newTiles.cnt = tiles;
-
- // pass new tile list to glThread
- synchronized (this) {
- for (int i = 0; i < curTiles.cnt; i++) {
- boolean found = false;
-
- for (int j = 0; j < drawTiles.cnt && !found; j++)
- if (curTiles.tiles[i] == drawTiles.tiles[j])
- found = true;
-
- for (int j = 0; j < newTiles.cnt && !found; j++)
- if (curTiles.tiles[i] == newTiles.tiles[j])
- found = true;
-
- if (!found)
- curTiles.tiles[i].isActive = false;
- }
-
- for (int i = 0; i < tiles; i++)
- newTiles.tiles[i].isActive = true;
-
- TilesData tmp = curTiles;
- curTiles = newTiles;
- curTiles.cnt = tiles;
- newTiles = tmp;
-
- mCurPosition = mapPosition;
-
- mUpdateTiles = true;
- }
-
- if (mJobList.size() > 0) {
- updateTileDistances(mJobList, mapPosition);
- Collections.sort(mJobList);
- mMapView.addJobs(mJobList);
- }
-
- return true;
- }
-
- private static void clearTile(MapTile t) {
- t.newData = false;
- t.isLoading = false;
- t.isReady = false;
-
- LineLayers.clear(t.lineLayers);
- PolygonLayers.clear(t.polygonLayers);
-
- t.labels = null;
- t.lineLayers = null;
- t.polygonLayers = null;
-
- if (t.vbo != null) {
- synchronized (mVBOs) {
- mVBOs.add(t.vbo);
- }
- t.vbo = null;
- }
-
- QuadTree.remove(t);
}
/**
* called by MapView when position or map settings changes
*/
@Override
- public synchronized void redrawTiles(boolean clear) {
- boolean changedPos = false;
- boolean changedZoom = false;
- MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
+ public void redrawTiles(boolean clear) {
+ TileLoader.redrawTiles(clear);
+ }
- if (mapPosition == null) {
- Log.d(TAG, ">>> no map position");
- return;
- }
+ static void updatePosition(MapPosition mapPosition) {
+ // synchronized (MapRenderer.lock) {
+ mCurPosition = mapPosition;
+ // }
+ }
- if (clear) {
- mInitial = true;
- synchronized (this) {
+ static TilesData updateTiles(MapPosition mapPosition, TilesData tiles) {
+ synchronized (MapRenderer.lock) {
- for (MapTile t : mTiles)
- clearTile(t);
-
- mTiles.clear();
- mTilesLoaded.clear();
- QuadTree.init();
- curTiles.cnt = 0;
- mBufferMemoryUsage = 0;
- }
- }
-
- byte zoomLevel = mapPosition.zoomLevel;
- float scale = mapPosition.scale;
-
- long tileX = MercatorProjection.pixelXToTileX(mapPosition.x, zoomLevel)
- * Tile.TILE_SIZE;
- long tileY = MercatorProjection.pixelYToTileY(mapPosition.y, zoomLevel)
- * Tile.TILE_SIZE;
-
- int zdir = 0;
- if (mInitial || mPrevZoom != zoomLevel) {
- changedZoom = true;
- mPrevScale = scale;
- }
- else if (tileX != mTileX || tileY != mTileY) {
- if (mPrevScale - scale > 0 && scale > 1.2)
- zdir = 1;
- mPrevScale = scale;
- changedPos = true;
- }
- else if (mPrevScale - scale > 0.2 || mPrevScale - scale < -0.2) {
- if (mPrevScale - scale > 0 && scale > 1.2)
- zdir = 1;
- mPrevScale = scale;
- changedPos = true;
- }
-
- if (mInitial) {
mCurPosition = mapPosition;
- mInitial = false;
+
+ for (int i = 0; i < curTiles.cnt; i++)
+ curTiles.tiles[i].isActive = false;
+
+ TilesData tmp = curTiles;
+ curTiles = tiles;
+
+ for (int i = 0; i < curTiles.cnt; i++)
+ curTiles.tiles[i].isActive = true;
+
+ for (int j = 0; j < drawTiles.cnt; j++)
+ drawTiles.tiles[j].isActive = true;
+
+ mUpdateTiles = true;
+
+ return tmp;
}
- mTileX = tileX;
- mTileY = tileY;
- mPrevZoom = zoomLevel;
+ }
- if (changedZoom) {
- // need to update visible list first when zoom level changes
- // as scaling is relative to the tiles of current zoom-level
- updateVisibleList(mapPosition, 0);
- } else {
- // pass new position to glThread
- synchronized (this) {
- // do not change position while drawing
- mCurPosition = mapPosition;
- }
+ static void addVBO(VertexBufferObject vbo) {
+ synchronized (mVBOs) {
+ mVBOs.add(vbo);
}
-
- if (!MapView.debugFrameTime)
- mMapView.requestRender();
-
- if (changedPos)
- updateVisibleList(mapPosition, zdir);
-
- if (changedPos || changedZoom) {
- int remove = mTiles.size() - CACHE_TILES;
- if (remove > 10)
- limitCache(mapPosition, remove);
- }
-
- int size = mTilesLoaded.size();
- if (size > MAX_TILES_IN_QUEUE)
- limitLoadQueue(size);
-
}
/**
@@ -616,11 +182,10 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
public synchronized boolean passTile(JobTile jobTile) {
MapTile tile = (MapTile) jobTile;
- if (tile.isCanceled) {
+ if (!tile.isLoading) {
// no one should be able to use this tile now, mapgenerator passed it,
// glthread does nothing until newdata is set.
Log.d(TAG, "passTile: canceled " + tile);
- tile.isLoading = false;
return true;
}
@@ -644,9 +209,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (!MapView.debugFrameTime)
mMapView.requestRender();
- synchronized (mTilesLoaded) {
- mTilesLoaded.add(0, tile);
- }
+ TileLoader.addTileLoaded(tile);
return true;
}
@@ -655,37 +218,46 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// ... asus has just 16 bit?!
// private static final float depthStep = 0.00000011920928955078125f;
+ private static boolean mRotate = false;
+
private static void setMatrix(MapTile tile, float div, int offset) {
float x, y, scale;
- scale = (float) (2.0 * mDrawPosition.scale / (mHeight * div));
- x = (float) (tile.pixelX - mDrawPosition.x * div);
- y = (float) (tile.pixelY - mDrawPosition.y * div);
+ if (mRotate) {
+ scale = (float) (1.0 * mDrawPosition.scale / (mHeight * div));
+ x = (float) (tile.pixelX - mDrawPosition.x * div);
+ y = (float) (tile.pixelY - mDrawPosition.y * div);
- mMVPMatrix[12] = x * scale * mAspect;
- mMVPMatrix[13] = -(y + Tile.TILE_SIZE) * scale;
- // increase the 'distance' with each tile drawn.
- mMVPMatrix[14] = -1 + offset * 0.01f; // depthStep; // 0.01f;
- mMVPMatrix[0] = scale * mAspect / COORD_MULTIPLIER;
- mMVPMatrix[5] = scale / COORD_MULTIPLIER;
+ Matrix.setIdentityM(mMVPMatrix, 0);
- // Matrix.setIdentityM(mMVPMatrix, 0);
- //
- // Matrix.scaleM(mMVPMatrix, 0, scale / COORD_MULTIPLIER,
- // scale / COORD_MULTIPLIER, 1);
- //
- // Matrix.translateM(mMVPMatrix, 0, x * COORD_MULTIPLIER, -(y + Tile.TILE_SIZE)
- // * COORD_MULTIPLIER, 0);
- //
- // Matrix.setRotateM(mRotateMatrix, 0, mDrawPosition.angle, 0, 0, 1);
- //
- // Matrix.multiplyMM(mMVPMatrix, 0, mRotateMatrix, 0, mMVPMatrix, 0);
- //
- // Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
+ Matrix.scaleM(mMVPMatrix, 0, scale / COORD_MULTIPLIER,
+ scale / COORD_MULTIPLIER, 1);
+
+ Matrix.translateM(mMVPMatrix, 0,
+ x * COORD_MULTIPLIER,
+ -(y + Tile.TILE_SIZE) * COORD_MULTIPLIER,
+ -1 + offset * 0.01f);
+
+ Matrix.multiplyMM(mMVPMatrix, 0, mRotateMatrix, 0, mMVPMatrix, 0);
+
+ Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
+ }
+ else {
+ scale = (float) (2.0 * mDrawPosition.scale / (mHeight * div));
+ x = (float) (tile.pixelX - mDrawPosition.x * div);
+ y = (float) (tile.pixelY - mDrawPosition.y * div);
+
+ mMVPMatrix[12] = x * scale * mAspect;
+ mMVPMatrix[13] = -(y + Tile.TILE_SIZE) * scale;
+ // increase the 'distance' with each tile drawn.
+ mMVPMatrix[14] = -1 + offset * 0.01f; // depthStep; // 0.01f;
+ mMVPMatrix[0] = scale * mAspect / COORD_MULTIPLIER;
+ mMVPMatrix[5] = scale / COORD_MULTIPLIER;
+ }
}
- private static boolean setTileScissor(MapTile tile, float div) {
+ private static boolean isVisible(MapTile tile, float div) {
double dx, dy, scale;
if (div == 0) {
@@ -773,8 +345,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
+ sbuf.limit() + " "
+ sbuf.remaining() + " "
+ PolygonLayers.sizeOf(tile.polygonLayers) + " "
- + tile.isCanceled + " "
- + tile.isLoading + " "
+ tile.rel);
tile.lineOffset *= SHORT_BYTES;
@@ -790,7 +360,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
+ sbuf.limit() + " "
+ sbuf.remaining() + " "
+ LineLayers.sizeOf(tile.lineLayers)
- + tile.isCanceled + " "
+ tile.isLoading + " "
+ tile.rel);
@@ -864,6 +433,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (MapView.debugFrameTime)
start = SystemClock.uptimeMillis();
+ mRotate = mMapView.enableRotation;
+
if (mUpdateColor && mClearColor != null) {
glClearColor(mClearColor[0], mClearColor[1], mClearColor[2], mClearColor[3]);
mUpdateColor = false;
@@ -871,7 +442,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
GLES20.glDepthMask(true);
- // Note: i have the impression it is faster to also clear the
+ // Note: having the impression it is faster to also clear the
// stencil buffer even when not needed. probaly otherwise it
// is masked out from the depth buffer as they share the same
// memory region afaik
@@ -879,11 +450,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
| GLES20.GL_DEPTH_BUFFER_BIT
| GLES20.GL_STENCIL_BUFFER_BIT);
- if (mInitial)
- return;
-
// get position and current tiles to draw
- synchronized (this) {
+ synchronized (MapRenderer.lock) {
mDrawPosition = mCurPosition;
if (mUpdateTiles) {
@@ -904,7 +472,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
for (int i = 0; i < tileCnt; i++) {
MapTile tile = tiles[i];
- if (!setTileScissor(tile, 1))
+ if (!isVisible(tile, 1))
continue;
if (tile.texture == null && TextRenderer.drawToTexture(tile))
@@ -939,6 +507,11 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (updateTextures > 0)
TextRenderer.compileTextures();
+ if (mRotate) {
+ Matrix.setRotateM(mRotateMatrix, 0, mDrawPosition.angle, 0, 0, 1);
+ Matrix.transposeM(mRotTMatrix, 0, mRotateMatrix, 0);
+ }
+
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
for (int i = 0; i < tileCnt; i++) {
@@ -970,10 +543,13 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (scale < 1)
scale = 1;
+ // scale = (1.0f * mDrawPosition.scale / mHeight);
+ // TextRenderer.beginDraw(scale);
+
if (z >= MapGenerator.STROKE_MAX_ZOOM_LEVEL)
- TextRenderer.beginDraw(FloatMath.sqrt(s) / scale);
+ TextRenderer.beginDraw(FloatMath.sqrt(s) / scale, mRotTMatrix);
else
- TextRenderer.beginDraw(s);
+ TextRenderer.beginDraw(s, mRotTMatrix);
for (int i = 0; i < tileCnt; i++) {
if (!tiles[i].isVisible || tiles[i].texture == null)
@@ -1055,7 +631,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (c == null)
continue;
- if (!setTileScissor(c, 2)) {
+ if (!isVisible(c, 2)) {
drawn++;
continue;
}
@@ -1107,16 +683,13 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
Log.d(TAG, "SurfaceChanged:" + width + " " + height);
- mTilesLoaded.clear();
- mTiles.clear();
-
- ShortPool.init();
- QuadTree.init();
+ // mTilesLoaded.clear();
+ // mTiles.clear();
// LineLayers.finish();
- drawTiles = newTiles = curTiles = null;
+ drawTiles = curTiles = null;
mBufferMemoryUsage = 0;
- mInitial = true;
+ // mInitial = true;
if (width <= 0 || height <= 0)
return;
@@ -1127,22 +700,20 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mHeight = height;
mAspect = (float) height / width;
- // Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f, 0.5f, -1, 1);
+ Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f, 0.5f, -1, 1);
glViewport(0, 0, width, height);
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
* (mHeight / (Tile.TILE_SIZE / 2) + 2);
+ TileLoader.init(mMapView, width, height, numTiles);
+
drawTiles = new TilesData(numTiles);
- newTiles = new TilesData(numTiles);
curTiles = new TilesData(numTiles);
- // Log.d(TAG, "using: " + numTiles + " + cache: " + CACHE_TILES);
- GlUtils.checkGlError("pre glGenBuffers");
-
// Set up vertex buffer objects
- int numVBO = (CACHE_TILES + numTiles);
+ int numVBO = (CACHE_TILES + (numTiles * 2));
int[] mVboIds = new int[numVBO];
glGenBuffers(numVBO, mVboIds, 0);
GlUtils.checkGlError("glGenBuffers");
@@ -1155,8 +726,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// Set up textures
TextRenderer.init(numTiles);
- // glDisable(GL_DITHER);
-
if (mClearColor != null) {
glClearColor(mClearColor[0], mClearColor[1],
mClearColor[2], mClearColor[3]);
@@ -1199,10 +768,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mFillCoords[6] = max;
mFillCoords[7] = min;
- // int i[] = new int[1];
- // GLES20.glGetIntegerv(GLES20.GL_, i, 0);
- // Log.d(TAG, " >>>> " + i[0]);
-
LineLayers.init();
PolygonLayers.init();
}
diff --git a/src/org/mapsforge/android/glrenderer/MapTile.java b/src/org/mapsforge/android/glrenderer/MapTile.java
index 172fe64f..2d56f676 100644
--- a/src/org/mapsforge/android/glrenderer/MapTile.java
+++ b/src/org/mapsforge/android/glrenderer/MapTile.java
@@ -19,25 +19,51 @@ import org.mapsforge.android.mapgenerator.JobTile;
class MapTile extends JobTile {
byte lastDraw = 0;
- // VBO layout:
- // 16 bytes fill coordinates
- // n bytes polygon vertices
- // m bytes lines vertices
+ /**
+ * VBO layout:
+ * - 16 bytes fill coordinates
+ * - n bytes polygon vertices
+ * - m bytes lines vertices
+ */
VertexBufferObject vbo;
- // polygonOffset in vbo is always 16 bytes,
+ /**
+ * polygonOffset in vbo is always 16 bytes,
+ */
int lineOffset;
TextTexture texture;
- // Tile data set by MapGenerator:
+ /**
+ * Tile data set by MapGenerator:
+ */
LineLayer lineLayers;
PolygonLayer polygonLayers;
TextItem labels;
+ /**
+ * tile has new data to upload to gl
+ */
boolean newData;
- // pointer to access relatives in TileTree
+ /**
+ * tile is loaded and ready for drawing.
+ */
+ boolean isReady;
+
+ /**
+ * tile is in view region.
+ */
+ boolean isVisible;
+
+ /**
+ * tile is used by render thread. set by updateVisibleList (main thread).
+ */
+ boolean isActive;
+
+ /**
+ * pointer to access relatives in TileTree
+ */
QuadTree rel;
MapTile(int tileX, int tileY, byte zoomLevel) {
diff --git a/src/org/mapsforge/android/glrenderer/Shaders.java b/src/org/mapsforge/android/glrenderer/Shaders.java
index 8c4743dd..565988f7 100644
--- a/src/org/mapsforge/android/glrenderer/Shaders.java
+++ b/src/org/mapsforge/android/glrenderer/Shaders.java
@@ -111,14 +111,39 @@ class Shaders {
+ "attribute vec4 vertex;"
+ "attribute vec2 tex_coord;"
+ "uniform mat4 mvp;"
+ + "uniform mat4 rotation;"
+ "uniform float scale;"
+ "varying vec2 tex_c;"
+ "const vec2 div = vec2(1.0/4096.0,1.0/2048.0);"
+ "void main() {"
- + " gl_Position = mvp * vec4(vertex.xy + (vertex.zw / scale), 0.0, 1.0);"
- + " tex_c = tex_coord * div;"
+ + " if (mod(vertex.x, 2.0) == 0.0){"
+ + " gl_Position = mvp * vec4(vertex.xy + vertex.zw / scale, 0.0, 1.0);"
+ + " } else {"
+ + " vec4 dir = rotation * vec4(vertex.zw / scale, 0.0, 1.0);"
+ + " gl_Position = mvp * vec4(vertex.xy + dir.xy, 0.0, 1.0);"
+ + " }"
+ + " tex_c = tex_coord * div;"
+ "}";
+ // final static String textVertexShader = ""
+ // + "precision highp float; "
+ // + "attribute vec4 vertex;"
+ // + "attribute vec2 tex_coord;"
+ // + "uniform mat4 mvp;"
+ // + "uniform mat4 rotation;"
+ // + "uniform float scale;"
+ // + "varying vec2 tex_c;"
+ // + "const vec2 div = vec2(1.0/4096.0,1.0/2048.0);"
+ // + "void main() {"
+ // + " if (mod(vertex.x, 2.0) == 0.0){"
+ // + " gl_Position = mvp * vec4(vertex.xy + vertex.zw / scale, 0.0, 1.0);"
+ // + " } else {"
+ // + " vec4 dir = rotation * vec4(vertex.zw / scale, 0.0, 1.0);"
+ // + " gl_Position = mvp * vec4(vertex.xy + dir.xy, 0.0, 1.0);"
+ // + " }"
+ // + " tex_c = tex_coord * div;"
+ // + "}";
+
final static String textFragmentShader = ""
+ "precision highp float;"
+ "uniform sampler2D tex;"
diff --git a/src/org/mapsforge/android/glrenderer/TextRenderer.java b/src/org/mapsforge/android/glrenderer/TextRenderer.java
index e17242f1..cfada51a 100644
--- a/src/org/mapsforge/android/glrenderer/TextRenderer.java
+++ b/src/org/mapsforge/android/glrenderer/TextRenderer.java
@@ -32,7 +32,9 @@ import android.util.Log;
public class TextRenderer {
private final static int TEXTURE_WIDTH = 512;
private final static int TEXTURE_HEIGHT = 256;
- private final static float SCALE_FACTOR = 8.0f;
+ private final static float SCALE = 8.0f;
+ private final static int LBIT_MASK = 0xfffffffe;
+ private final static int L2BIT_MASK = 0xfffffffc;
final static int INDICES_PER_SPRITE = 6;
final static int VERTICES_PER_SPRITE = 4;
@@ -53,6 +55,7 @@ public class TextRenderer {
private static int mTextProgram;
private static int hTextUVPMatrix;
+ private static int hTextRotationMatrix;
private static int hTextVertex;
private static int hTextScale;
private static int hTextTextureCoord;
@@ -99,6 +102,8 @@ public class TextRenderer {
Shaders.textFragmentShader);
hTextUVPMatrix = GLES20.glGetUniformLocation(mTextProgram, "mvp");
+ hTextRotationMatrix = GLES20.glGetUniformLocation(mTextProgram, "rotation");
+
hTextVertex = GLES20.glGetAttribLocation(mTextProgram, "vertex");
hTextScale = GLES20.glGetUniformLocation(mTextProgram, "scale");
hTextTextureCoord = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
@@ -283,10 +288,10 @@ public class TextRenderer {
float hh = height / 2.0f;
if (t.caption != null) {
- x1 = x3 = (short) (SCALE_FACTOR * (-hw));
- y1 = y3 = (short) (SCALE_FACTOR * (-hh));
- x2 = x4 = (short) (SCALE_FACTOR * (hw));
- y2 = y4 = (short) (SCALE_FACTOR * (hh));
+ x1 = x3 = (short) (SCALE * (-hw));
+ y1 = y3 = (short) (SCALE * (-hh));
+ x2 = x4 = (short) (SCALE * (hw));
+ y2 = y4 = (short) (SCALE * (hh));
}
else {
float vx = t.x1 - t.x2;
@@ -298,26 +303,45 @@ public class TextRenderer {
float ux = -vy;
float uy = vx;
- x1 = (short) (SCALE_FACTOR * (vx * hw + ux * hh));
- y1 = (short) (SCALE_FACTOR * (vy * hw + uy * hh));
+ // int dx = (int) (vx * SCALE) & L2BIT_MASK;
+ // int dy = (int) (vy * SCALE) & L2BIT_MASK;
+ //
+ // x1 = (short) dx;
+ // y1 = (short) dy;
+ //
+ // x2 = (short) (dx | 1);
+ // y3 = (short) (dy | 1);
+ //
+ // x4 = (short) (dx | 3);
+ // y4 = (short) (dy | 3);
+ //
+ // x3 = (short) (dx | 2);
+ // y2 = (short) (dy | 2);
- x2 = (short) (SCALE_FACTOR * (-vx * hw + ux * hh));
- y3 = (short) (SCALE_FACTOR * (-vy * hw + uy * hh));
-
- x4 = (short) (SCALE_FACTOR * (-vx * hw - ux * hh));
- y4 = (short) (SCALE_FACTOR * (-vy * hw - uy * hh));
-
- x3 = (short) (SCALE_FACTOR * (vx * hw - ux * hh));
- y2 = (short) (SCALE_FACTOR * (vy * hw - uy * hh));
+ x1 = (short) (SCALE * (vx * hw + ux * hh));
+ y1 = (short) (SCALE * (vy * hw + uy * hh));
+ x2 = (short) (SCALE * (-vx * hw + ux * hh));
+ y3 = (short) (SCALE * (-vy * hw + uy * hh));
+ x4 = (short) (SCALE * (-vx * hw - ux * hh));
+ y4 = (short) (SCALE * (-vy * hw - uy * hh));
+ x3 = (short) (SCALE * (vx * hw - ux * hh));
+ y2 = (short) (SCALE * (vy * hw - uy * hh));
}
- short u1 = (short) (SCALE_FACTOR * x);
- short v1 = (short) (SCALE_FACTOR * y);
- short u2 = (short) (SCALE_FACTOR * (x + width));
- short v2 = (short) (SCALE_FACTOR * (y + height));
+ short u1 = (short) (SCALE * x);
+ short v1 = (short) (SCALE * y);
+ short u2 = (short) (SCALE * (x + width));
+ short v2 = (short) (SCALE * (y + height));
+
+ // pack caption/way-text info in lowest bit
+ short tx;
+ if (t.caption == null)
+ tx = (short) ((int) (SCALE * t.x) & LBIT_MASK | 0);
+ else
+ tx = (short) ((int) (SCALE * t.x) & LBIT_MASK | 1);
+
+ short ty = (short) (SCALE * t.y);
- short tx = (short) (SCALE_FACTOR * t.x);
- short ty = (short) (SCALE_FACTOR * t.y);
// top-left
buf[pos++] = tx;
buf[pos++] = ty;
@@ -366,7 +390,7 @@ public class TextRenderer {
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mBitmap,
mBitmapFormat, mBitmapType);
- GLES20.glFlush();
+ // GLES20.glFlush();
return true;
}
@@ -397,13 +421,14 @@ public class TextRenderer {
mShortBuffer);
}
- static void beginDraw(float scale) {
+ static void beginDraw(float scale, float[] rotation) {
GLES20.glUseProgram(mTextProgram);
GLES20.glEnableVertexAttribArray(hTextTextureCoord);
GLES20.glEnableVertexAttribArray(hTextVertex);
GLES20.glUniform1f(hTextScale, scale);
+ GLES20.glUniformMatrix4fv(hTextRotationMatrix, 1, false, rotation, 0);
if (debug) {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
diff --git a/src/org/mapsforge/android/glrenderer/TileLoader.java b/src/org/mapsforge/android/glrenderer/TileLoader.java
new file mode 100644
index 00000000..0c5cded2
--- /dev/null
+++ b/src/org/mapsforge/android/glrenderer/TileLoader.java
@@ -0,0 +1,530 @@
+/*
+ * Copyright 2012 Hannes Janetzek
+ *
+ * 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 .
+ */
+package org.mapsforge.android.glrenderer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+import org.mapsforge.android.MapView;
+import org.mapsforge.android.glrenderer.MapRenderer.TilesData;
+import org.mapsforge.android.mapgenerator.JobTile;
+import org.mapsforge.core.MapPosition;
+import org.mapsforge.core.MercatorProjection;
+import org.mapsforge.core.Tile;
+
+import android.util.FloatMath;
+import android.util.Log;
+
+// for lack of a better name... maybe TileManager?
+
+/**
+ * Update list of visible tiles and passes them to MapRenderer, when not available tiles are created and added to
+ * JobQueue (mapView.addJobs) for loading by MapGenerator class
+ */
+
+public class TileLoader {
+ private static final String TAG = "TileLoader";
+
+ private static final int MAX_TILES_IN_QUEUE = 40;
+ private static final int CACHE_TILES_MAX = 200;
+ // private static final int MB = 1024 * 1024;
+ // private static final int LIMIT_BUFFERS = 16 * MB;
+
+ private static int CACHE_TILES = CACHE_TILES_MAX;
+
+ private static MapView mMapView;
+
+ private static ArrayList mJobList;
+ // private static ArrayList mVBOs;
+
+ // all tiles currently referenced
+ private static ArrayList mTiles;
+ // private static ArrayList mTilesActive;
+ // tiles that have new data to upload, see passTile()
+ private static ArrayList mTilesLoaded;
+
+ // current center tile, values used to check if position has
+ // changed for updating current tile list
+ private static long mTileX, mTileY;
+ private static float mPrevScale;
+ private static byte mPrevZoom;
+ private static boolean mInitial;
+
+ // private static MapPosition mCurPosition, mDrawPosition;
+ private static int mWidth, mHeight;
+
+ private static TilesData newTiles; // , curTiles, drawTiles;
+
+ static void init(MapView mapView, int w, int h, int numTiles) {
+ mMapView = mapView;
+
+ ShortPool.init();
+ QuadTree.init();
+
+ mJobList = new ArrayList();
+ mTiles = new ArrayList();
+ mTilesLoaded = new ArrayList(30);
+
+ mInitial = true;
+ mWidth = w;
+ mHeight = h;
+
+ newTiles = new TilesData(numTiles);
+ }
+
+ static void redrawTiles(boolean clear) {
+
+ boolean changedPos = false;
+ boolean changedZoom = false;
+ MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
+
+ if (mapPosition == null) {
+ Log.d(TAG, ">>> no map position");
+ return;
+ }
+
+ if (clear) {
+ mInitial = true;
+ synchronized (MapRenderer.lock) {
+
+ for (MapTile t : mTiles)
+ clearTile(t);
+
+ mTiles.clear();
+ mTilesLoaded.clear();
+ QuadTree.init();
+ // curTiles.cnt = 0;
+ // mBufferMemoryUsage = 0;
+ }
+ }
+
+ byte zoomLevel = mapPosition.zoomLevel;
+ float scale = mapPosition.scale;
+
+ long tileX = MercatorProjection.pixelXToTileX(mapPosition.x, zoomLevel)
+ * Tile.TILE_SIZE;
+ long tileY = MercatorProjection.pixelYToTileY(mapPosition.y, zoomLevel)
+ * Tile.TILE_SIZE;
+
+ int zdir = 0;
+ if (mInitial || mPrevZoom != zoomLevel) {
+ changedZoom = true;
+ mPrevScale = scale;
+ }
+ else if (tileX != mTileX || tileY != mTileY) {
+ if (mPrevScale - scale > 0 && scale > 1.2)
+ zdir = 1;
+ mPrevScale = scale;
+ changedPos = true;
+ }
+ else if (mPrevScale - scale > 0.2 || mPrevScale - scale < -0.2) {
+ if (mPrevScale - scale > 0 && scale > 1.2)
+ zdir = 1;
+ mPrevScale = scale;
+ changedPos = true;
+ }
+
+ if (mInitial) {
+ // mCurPosition = mapPosition;
+ mInitial = false;
+ }
+
+ mTileX = tileX;
+ mTileY = tileY;
+ mPrevZoom = zoomLevel;
+
+ if (changedZoom) {
+ // need to update visible list first when zoom level changes
+ // as scaling is relative to the tiles of current zoom-level
+ updateVisibleList(mapPosition, 0);
+ } else {
+ // pass new position to glThread
+
+ MapRenderer.updatePosition(mapPosition);
+
+ // synchronized () {
+ // // do not change position while drawing
+ // mCurPosition = mapPosition;
+ // }
+ }
+
+ if (!MapView.debugFrameTime)
+ mMapView.requestRender();
+
+ if (changedPos)
+ updateVisibleList(mapPosition, zdir);
+
+ if (changedPos || changedZoom) {
+ int remove = mTiles.size() - CACHE_TILES;
+ if (remove > 50)
+ limitCache(mapPosition, remove);
+ }
+
+ int size = mTilesLoaded.size();
+ if (size > MAX_TILES_IN_QUEUE)
+ limitLoadQueue(size);
+
+ }
+
+ private static boolean updateVisibleList(MapPosition mapPosition, int zdir) {
+ double x = mapPosition.x;
+ double y = mapPosition.y;
+ byte zoomLevel = mapPosition.zoomLevel;
+ float scale = mapPosition.scale;
+
+ double add = 1.0f / scale;
+ int offsetX = (int) ((mWidth >> 1) * add) + Tile.TILE_SIZE;
+ int offsetY = (int) ((mHeight >> 1) * add) + Tile.TILE_SIZE;
+
+ long pixelRight = (long) x + offsetX;
+ long pixelBottom = (long) y + offsetY;
+ long pixelLeft = (long) x - offsetX;
+ long pixelTop = (long) y - offsetY;
+
+ int tileLeft = MercatorProjection.pixelXToTileX(pixelLeft, zoomLevel);
+ int tileTop = MercatorProjection.pixelYToTileY(pixelTop, zoomLevel);
+ int tileRight = MercatorProjection.pixelXToTileX(pixelRight, zoomLevel);
+ int tileBottom = MercatorProjection.pixelYToTileY(pixelBottom, zoomLevel);
+
+ mJobList.clear();
+
+ // set non processed tiles to isLoading == false
+ mMapView.addJobs(null);
+
+ int tiles = 0;
+ if (newTiles == null)
+ return false;
+
+ int max = newTiles.tiles.length - 1;
+
+ for (int yy = tileTop; yy <= tileBottom; yy++) {
+ for (int xx = tileLeft; xx <= tileRight; xx++) {
+
+ if (tiles == max)
+ break;
+
+ MapTile tile = QuadTree.getTile(xx, yy, zoomLevel);
+
+ if (tile == null) {
+ tile = new MapTile(xx, yy, zoomLevel);
+
+ QuadTree.add(tile);
+ mTiles.add(tile);
+ }
+
+ newTiles.tiles[tiles++] = tile;
+
+ if (!(tile.isLoading || tile.newData || tile.isReady)) {
+ mJobList.add(tile);
+ }
+
+ if (zdir > 0 && zoomLevel > 0) {
+ // prefetch parent
+ MapTile parent = tile.rel.parent.tile;
+
+ if (parent == null) {
+ parent = new MapTile(xx >> 1, yy >> 1, (byte) (zoomLevel - 1));
+
+ QuadTree.add(parent);
+ mTiles.add(parent);
+ }
+
+ if (!(parent.isLoading || parent.isReady || parent.newData)) {
+ if (!mJobList.contains(parent))
+ mJobList.add(parent);
+ }
+ }
+ }
+ }
+
+ // pass new tile list to glThread
+ newTiles.cnt = tiles;
+ newTiles = MapRenderer.updateTiles(mapPosition, newTiles);
+
+ // pass new tile list to glThread
+ // synchronized (MapRenderer.lock) {
+ //
+ // for (int i = 0; i < curTiles.cnt; i++)
+ // curTiles.tiles[i].isActive = false;
+ //
+ // for (int j = 0; j < drawTiles.cnt; j++)
+ // drawTiles.tiles[j].isActive = true;
+ //
+ // for (int i = 0; i < tiles; i++)
+ // newTiles.tiles[i].isActive = true;
+ //
+ // TilesData tmp = curTiles;
+ // curTiles = newTiles;
+ // curTiles.cnt = tiles;
+ // newTiles = tmp;
+ //
+ // mCurPosition = mapPosition;
+ //
+ // mUpdateTiles = true;
+ // }
+
+ if (mJobList.size() > 0) {
+ updateTileDistances(mJobList, mapPosition);
+ Collections.sort(mJobList);
+ mMapView.addJobs(mJobList);
+ }
+
+ return true;
+ }
+
+ private static void clearTile(MapTile t) {
+ t.newData = false;
+ t.isLoading = false;
+ t.isReady = false;
+
+ LineLayers.clear(t.lineLayers);
+ PolygonLayers.clear(t.polygonLayers);
+
+ t.labels = null;
+ t.lineLayers = null;
+ t.polygonLayers = null;
+
+ if (t.vbo != null) {
+ MapRenderer.addVBO(t.vbo);
+ t.vbo = null;
+ }
+
+ QuadTree.remove(t);
+ }
+
+ private static boolean childIsActive(MapTile t) {
+ MapTile c = null;
+
+ for (int i = 0; i < 4; i++) {
+ if (t.rel.child[i] == null)
+ continue;
+
+ c = t.rel.child[i].tile;
+ if (c != null && c.isActive && !(c.isReady || c.newData))
+ return true;
+ }
+
+ return false;
+ }
+
+ // FIXME still the chance that one jumped two zoomlevels between
+ // cur and draw. should use reference counter instead
+ private static boolean tileInUse(MapTile t) {
+ byte z = mPrevZoom;
+
+ if (t.isActive) {
+ return true;
+
+ } else if (t.zoomLevel == z + 1) {
+ MapTile p = t.rel.parent.tile;
+
+ if (p != null && p.isActive && !(p.isReady || p.newData))
+ return true;
+
+ } else if (t.zoomLevel == z + 2) {
+ MapTile p = t.rel.parent.parent.tile;
+
+ if (p != null && p.isActive && !(p.isReady || p.newData))
+ return true;
+
+ } else if (t.zoomLevel == z - 1) {
+ if (childIsActive(t))
+ return true;
+
+ } else if (t.zoomLevel == z - 2) {
+ for (QuadTree c : t.rel.child) {
+ if (c == null)
+ continue;
+
+ if (c.tile != null && childIsActive(c.tile))
+ return true;
+ }
+ } else if (t.zoomLevel == z - 3) {
+ for (QuadTree c : t.rel.child) {
+ if (c == null)
+ continue;
+
+ for (QuadTree c2 : c.child) {
+ if (c2 == null)
+ continue;
+
+ if (c2.tile != null && childIsActive(c2.tile))
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static void updateTileDistances(ArrayList> tiles,
+ MapPosition mapPosition) {
+ int h = (Tile.TILE_SIZE >> 1);
+ byte zoom = mapPosition.zoomLevel;
+ long x = (long) mapPosition.x;
+ long y = (long) mapPosition.y;
+
+ int diff;
+ long dx, dy;
+
+ // TODO this could need some fixing, and optimization
+ // to consider move/zoom direction
+
+ for (int i = 0, n = tiles.size(); i < n; i++) {
+ JobTile t = (JobTile) tiles.get(i);
+ diff = (t.zoomLevel - zoom);
+
+ if (diff == 0) {
+ dx = (t.pixelX + h) - x;
+ dy = (t.pixelY + h) - y;
+ // t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) * 0.25f;
+ t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * 0.25f;
+ } else if (diff > 0) {
+ // tile zoom level is child of current
+
+ if (diff < 3) {
+ dx = ((t.pixelX + h) >> diff) - x;
+ dy = ((t.pixelY + h) >> diff) - y;
+ }
+ else {
+ dx = ((t.pixelX + h) >> (diff >> 1)) - x;
+ dy = ((t.pixelY + h) >> (diff >> 1)) - y;
+ }
+ // t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy));
+ t.distance = FloatMath.sqrt((dx * dx + dy * dy));
+
+ } else {
+ // tile zoom level is parent of current
+ dx = ((t.pixelX + h) << -diff) - x;
+ dy = ((t.pixelY + h) << -diff) - y;
+
+ // t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) * (-diff * 0.5f);
+ t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * (-diff * 0.5f);
+ }
+ }
+ }
+
+ private static void limitCache(MapPosition mapPosition, int remove) {
+ int removes = remove;
+
+ int size = mTiles.size();
+ int tmp = size;
+
+ // remove orphaned tiles
+ for (int i = 0; i < size;) {
+ MapTile cur = mTiles.get(i);
+ // make sure tile cannot be used by GL or MapWorker Thread
+ if ((!cur.isActive) && (!cur.isLoading) && (!cur.newData)
+ && (!cur.isReady) && (!tileInUse(cur))) {
+
+ clearTile(cur);
+ mTiles.remove(i);
+ removes--;
+ size--;
+ // Log.d(TAG, "remove empty tile" + cur);
+ continue;
+ }
+ i++;
+ }
+
+ Log.d(TAG, "remove tiles: " + removes + " " + size + " " + tmp);
+
+ if (removes <= 0)
+ return;
+
+ updateTileDistances(mTiles, mapPosition);
+ Collections.sort(mTiles);
+
+ // boolean printAll = false;
+
+ for (int i = 1; i <= removes; i++) {
+
+ MapTile t = mTiles.remove(size - i);
+
+ synchronized (t) {
+ if (t.isActive) {
+ // dont remove tile used by renderthread
+ Log.d(TAG, "X not removing active " + t + " " + t.distance);
+
+ // if (printAll) {
+ // printAll = false;
+ // for (GLMapTile tt : mTiles)
+ // Log.d(TAG, ">>>" + tt + " " + tt.distance);
+ // }
+ mTiles.add(t);
+ } else if ((t.isReady || t.newData) && tileInUse(t)) {
+ // check if this tile could be used as proxy
+ Log.d(TAG, "X not removing proxy: " + t + " " + t.distance);
+ mTiles.add(t);
+ } else {
+ if (t.isLoading) {
+ Log.d(TAG, "X cancel loading " + t + " " + t.distance);
+ t.isLoading = false;
+ }
+ clearTile(t);
+ }
+ }
+ }
+ }
+
+ private static void limitLoadQueue(int remove) {
+ int size = remove;
+
+ synchronized (mTilesLoaded) {
+
+ // remove uploaded tiles
+ for (int i = 0; i < size;) {
+ MapTile t = mTilesLoaded.get(i);
+ // rel == null means tile is already removed by limitCache
+ if (!t.newData || t.rel == null) {
+ mTilesLoaded.remove(i);
+ size--;
+ continue;
+ }
+ i++;
+ }
+
+ // clear loaded but not used tiles
+ if (size < MAX_TILES_IN_QUEUE)
+ return;
+
+ while (size-- > MAX_TILES_IN_QUEUE - 20) {
+ MapTile t = mTilesLoaded.get(size);
+
+ synchronized (t) {
+ if (t.rel == null) {
+ mTilesLoaded.remove(size);
+ continue;
+ }
+
+ if (tileInUse(t)) {
+ // Log.d(TAG, "keep unused tile data: " + t + " " + t.isActive);
+ continue;
+ }
+
+ mTilesLoaded.remove(size);
+ mTiles.remove(t);
+ // Log.d(TAG, "remove unused tile data: " + t);
+ clearTile(t);
+ }
+ }
+ }
+ }
+
+ static void addTileLoaded(MapTile tile) {
+ synchronized (mTilesLoaded) {
+ mTilesLoaded.add(0, tile);
+ }
+ }
+}
diff --git a/src/org/mapsforge/android/mapgenerator/JobTile.java b/src/org/mapsforge/android/mapgenerator/JobTile.java
index d1bc845c..7bb89495 100644
--- a/src/org/mapsforge/android/mapgenerator/JobTile.java
+++ b/src/org/mapsforge/android/mapgenerator/JobTile.java
@@ -20,28 +20,20 @@ import org.mapsforge.core.Tile;
*
*/
public class JobTile extends Tile implements Comparable {
- /**
- * tile is loaded and ready for drawing. (set and used by render thread after uploading data to gl).
- */
- public boolean isReady;
+ // public final static int LOADING = 1;
+ // public final static int NEWDATA = 1 << 1;
+ // public final static int READY = 1 << 2;
+ // public final static int AVAILABLE = 1 << 1 | 1 << 2;
+ // public final static int CANCELED = 1 << 3;
+ // public int state;
/**
- * tile is removed from JobQueue and loading in DatabaseRenderer. set by MapWorker.
+ * tile is in JobQueue
*/
public boolean isLoading;
/**
- * tile is in view region. (set and used by render thread)
- */
- public boolean isVisible;
-
- /**
- * tile is used by render thread. set by updateVisibleList (main thread).
- */
- public boolean isActive;
-
- /**
- * distance from center, used in TileScheduler set by updateVisibleList.
+ * distance from map center.
*/
public float distance;
@@ -61,7 +53,8 @@ public class JobTile extends Tile implements Comparable {
public int compareTo(JobTile o) {
if (this.distance < o.distance) {
return -1;
- } else if (this.distance > o.distance) {
+ }
+ if (this.distance > o.distance) {
return 1;
}
return 0;
diff --git a/src/org/mapsforge/android/mapgenerator/MapDatabaseFactory.java b/src/org/mapsforge/android/mapgenerator/MapDatabaseFactory.java
index cb45de54..3eb4476d 100644
--- a/src/org/mapsforge/android/mapgenerator/MapDatabaseFactory.java
+++ b/src/org/mapsforge/android/mapgenerator/MapDatabaseFactory.java
@@ -61,8 +61,8 @@ public final class MapDatabaseFactory {
switch (mapDatabase) {
case MAP_READER:
return new org.mapsforge.database.mapfile.MapDatabase();
- case JSON_READER:
- return new org.mapsforge.database.json.MapDatabase();
+ case TEST_READER:
+ return new org.mapsforge.database.test.MapDatabase();
case POSTGIS_READER:
return new org.mapsforge.database.postgis.MapDatabase();
case PBMAP_READER:
diff --git a/src/org/mapsforge/android/mapgenerator/MapDatabases.java b/src/org/mapsforge/android/mapgenerator/MapDatabases.java
index 370f0347..fa21fc58 100644
--- a/src/org/mapsforge/android/mapgenerator/MapDatabases.java
+++ b/src/org/mapsforge/android/mapgenerator/MapDatabases.java
@@ -26,7 +26,7 @@ public enum MapDatabases {
/**
* ...
*/
- JSON_READER,
+ TEST_READER,
/**
* ...
diff --git a/src/org/mapsforge/android/swrenderer/MapGenerator.java b/src/org/mapsforge/android/swrenderer/MapGenerator.java
index f9223451..0f1d689d 100644
--- a/src/org/mapsforge/android/swrenderer/MapGenerator.java
+++ b/src/org/mapsforge/android/swrenderer/MapGenerator.java
@@ -91,7 +91,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
private static float PI180 = (float) (Math.PI / 180) / 1000000.0f;
private static float PIx4 = (float) Math.PI * 4;
- private Tile mCurrentTile;
+ private JobTile mCurrentTile;
private static long mCurrentTileY;
private static long mCurrentTileX;
private static long mCurrentTileZoom;
diff --git a/src/org/mapsforge/android/swrenderer/MapTile.java b/src/org/mapsforge/android/swrenderer/MapTile.java
index d6ddd684..bffca4c4 100644
--- a/src/org/mapsforge/android/swrenderer/MapTile.java
+++ b/src/org/mapsforge/android/swrenderer/MapTile.java
@@ -28,6 +28,8 @@ public class MapTile extends JobTile {
// private long mLoadTime;
private int mTextureID;
+ boolean isVisible;
+
/**
* @param tileX
* ...
diff --git a/src/org/mapsforge/app/TileMap.java b/src/org/mapsforge/app/TileMap.java
index f2c85662..897b44fe 100755
--- a/src/org/mapsforge/app/TileMap.java
+++ b/src/org/mapsforge/app/TileMap.java
@@ -104,6 +104,10 @@ public class TileMap extends MapActivity {
return true;
case R.id.menu_position:
+ mMapView.enableRotation(true);
+ return true;
+
+ case R.id.menu_rotation_enable:
return true;
case R.id.menu_position_my_location_enable:
diff --git a/src/org/mapsforge/core/Tile.java b/src/org/mapsforge/core/Tile.java
index ae98c5aa..7e744890 100644
--- a/src/org/mapsforge/core/Tile.java
+++ b/src/org/mapsforge/core/Tile.java
@@ -49,8 +49,6 @@ public class Tile {
*/
public final long pixelY;
- public volatile boolean isCanceled;
-
/**
* @param tileX
* the X number of the tile.
diff --git a/src/org/mapsforge/database/IMapDatabase.java b/src/org/mapsforge/database/IMapDatabase.java
index 2b106fd0..53adaa91 100644
--- a/src/org/mapsforge/database/IMapDatabase.java
+++ b/src/org/mapsforge/database/IMapDatabase.java
@@ -16,7 +16,7 @@ package org.mapsforge.database;
import java.io.File;
-import org.mapsforge.core.Tile;
+import org.mapsforge.android.mapgenerator.JobTile;
/**
*
@@ -38,7 +38,7 @@ public interface IMapDatabase {
* the callback which handles the extracted map elements.
* @return true if successful
*/
- public abstract QueryResult executeQuery(Tile tile,
+ public abstract QueryResult executeQuery(JobTile tile,
IMapDatabaseCallback mapDatabaseCallback);
/**
diff --git a/src/org/mapsforge/database/mapfile/MapDatabase.java b/src/org/mapsforge/database/mapfile/MapDatabase.java
index 1dc11917..335fba34 100644
--- a/src/org/mapsforge/database/mapfile/MapDatabase.java
+++ b/src/org/mapsforge/database/mapfile/MapDatabase.java
@@ -20,9 +20,9 @@ import java.io.RandomAccessFile;
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.mapsforge.android.mapgenerator.JobTile;
import org.mapsforge.core.MercatorProjection;
import org.mapsforge.core.Tag;
-import org.mapsforge.core.Tile;
import org.mapsforge.database.FileOpenResult;
import org.mapsforge.database.IMapDatabase;
import org.mapsforge.database.IMapDatabaseCallback;
@@ -204,7 +204,7 @@ public class MapDatabase implements IMapDatabase {
* org.mapsforge.map.reader.MapDatabaseCallback)
*/
@Override
- public QueryResult executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
+ public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
if (sMapFileHeader == null)
return QueryResult.FAILED;
diff --git a/src/org/mapsforge/database/pbmap/MapDatabase.java b/src/org/mapsforge/database/pbmap/MapDatabase.java
index c571c81b..7625d0c8 100644
--- a/src/org/mapsforge/database/pbmap/MapDatabase.java
+++ b/src/org/mapsforge/database/pbmap/MapDatabase.java
@@ -53,6 +53,7 @@ import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.RequestExpectContinue;
import org.apache.http.protocol.RequestUserAgent;
+import org.mapsforge.android.mapgenerator.JobTile;
import org.mapsforge.core.BoundingBox;
import org.mapsforge.core.GeoPoint;
import org.mapsforge.core.Tag;
@@ -106,7 +107,7 @@ public class MapDatabase implements IMapDatabase {
private IMapDatabaseCallback mMapGenerator;
private float mScaleFactor;
- private Tile mTile;
+ private JobTile mTile;
private FileOutputStream mCacheFile;
private long mContentLenth;
@@ -129,7 +130,7 @@ public class MapDatabase implements IMapDatabase {
});
@Override
- public QueryResult executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
+ public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
QueryResult result = QueryResult.SUCCESS;
mCacheFile = null;
@@ -194,7 +195,7 @@ public class MapDatabase implements IMapDatabase {
entity.consumeContent();
return QueryResult.FAILED;
}
- if (mTile.isCanceled) {
+ if (!mTile.isLoading) {
Log.d(TAG, "1 loading canceled " + mTile);
entity.consumeContent();
@@ -249,7 +250,7 @@ public class MapDatabase implements IMapDatabase {
mRequest = null;
// FIXME remove this stuff
- if (mTile.isCanceled) {
+ if (!mTile.isLoading) {
Log.d(TAG, "loading canceled " + mTile);
result = QueryResult.FAILED;
}
diff --git a/src/org/mapsforge/database/postgis/MapDatabase.java b/src/org/mapsforge/database/postgis/MapDatabase.java
index 25469bc2..7ce17e93 100644
--- a/src/org/mapsforge/database/postgis/MapDatabase.java
+++ b/src/org/mapsforge/database/postgis/MapDatabase.java
@@ -24,10 +24,10 @@ import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Properties;
+import org.mapsforge.android.mapgenerator.JobTile;
import org.mapsforge.core.BoundingBox;
import org.mapsforge.core.GeoPoint;
import org.mapsforge.core.Tag;
-import org.mapsforge.core.Tile;
import org.mapsforge.core.WebMercator;
import org.mapsforge.database.FileOpenResult;
import org.mapsforge.database.IMapDatabase;
@@ -45,7 +45,7 @@ import android.util.Log;
public class MapDatabase implements IMapDatabase {
private final static String TAG = "MapDatabase";
- private static final String QUERY = "SELECT tags, geom FROM __get_tile(?,?,?,false)";
+ private static final String QUERY = "SELECT tags, geom FROM __get_tile(?,?,?)";
private final float mScale = 1;
@@ -71,7 +71,7 @@ public class MapDatabase implements IMapDatabase {
private boolean connect() {
Connection conn = null;
- String dburl = "jdbc:postgresql://city.informatik.uni-bremen.de:5432/gis";
+ String dburl = "jdbc:postgresql://city.informatik.uni-bremen.de:5432/gis-2.0";
Properties dbOpts = new Properties();
dbOpts.setProperty("user", "osm");
@@ -102,7 +102,7 @@ public class MapDatabase implements IMapDatabase {
}
@Override
- public QueryResult executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
+ public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
if (connection == null) {
if (!connect())
return QueryResult.FAILED;
diff --git a/src/org/mapsforge/database/json/MapDatabase.java b/src/org/mapsforge/database/test/MapDatabase.java
similarity index 96%
rename from src/org/mapsforge/database/json/MapDatabase.java
rename to src/org/mapsforge/database/test/MapDatabase.java
index 164ba2eb..c62afb0d 100644
--- a/src/org/mapsforge/database/json/MapDatabase.java
+++ b/src/org/mapsforge/database/test/MapDatabase.java
@@ -12,10 +12,11 @@
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see .
*/
-package org.mapsforge.database.json;
+package org.mapsforge.database.test;
import java.io.File;
+import org.mapsforge.android.mapgenerator.JobTile;
import org.mapsforge.core.BoundingBox;
import org.mapsforge.core.MercatorProjection;
import org.mapsforge.core.Tag;
@@ -51,7 +52,7 @@ public class MapDatabase implements IMapDatabase {
// private static double HALF_PI = Math.PI / 2;
@Override
- public QueryResult executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
+ public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
long cx = tile.pixelX + (Tile.TILE_SIZE >> 1);
long cy = tile.pixelY + (Tile.TILE_SIZE >> 1);