osm-focus/src/dk/network42/osmfocus/OsmTileLayer.java

197 lines
5.6 KiB
Java

package dk.network42.osmfocus;
import android.content.ComponentCallbacks2;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v4.util.LruCache;
import android.util.Log;
import android.view.View;
public abstract class OsmTileLayer extends MapLayer {
private static final String TAG = "OsmTileLayer";
TileLruCache mTiles;
OsmTileProvider mProvider;
//View mView;
Handler mHandler;
Handler mMainHandler=null;
String mAttrib=null;
int mLastZoom = -1;
public OsmTileLayer(OsmTileProvider provider, int maxCacheSize) {
mProvider = provider;
mTiles = new TileLruCache(maxCacheSize);
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message inputMessage) {
//OsmTile t = (OsmTile) inputMessage.obj;
switch (inputMessage.what) {
case OsmTileProvider.TASK_DOWNLOAD_START:
case OsmTileProvider.TASK_DOWNLOAD_COMPLETE:
//Log.d(TAG, "Got download complete, tile"+t+" tile cache size="+mTiles.size());
if (mMainHandler != null)
mMainHandler.obtainMessage(MainActivity.INVALIDATE_VIEW, this).sendToTarget();
break;
}
}
};
}
static String urlFromType(int type) {
if (type==MapLayer.MAPTYPE_OSM) {
return "http://a.tile.openstreetmap.org";
} else if (type==MapLayer.MAPTYPE_OSMCYCLEMAP) {
return "http://a.tile.opencyclemap.org/cycle";
}
return "";
}
public void setMainHandler(Handler handler) {
mMainHandler = handler;
}
public void draw(Canvas canvas, RectF worldport, PaintConfig pcfg) {
for (int ii=0; ii<getNumLayers(); ii++) { // Sub-layers
drawTiles(canvas, worldport, pcfg, ii);
}
}
public void drawTiles(Canvas canvas, RectF worldport, PaintConfig pcfg, int layer) {
int zoom = getZoom(pcfg);
Rect vrect = OsmTile.worldport2tileport(worldport, zoom);
//Log.d(TAG, "TilePort="+vrect);
if (zoom != mLastZoom) {
mProvider.clearPending();
mLastZoom = zoom;
}
// RectF's are reversed top-bottom wise
int circles = (Math.max(vrect.right-vrect.left, vrect.bottom-vrect.top)+1)/2;
int cx = (vrect.right+vrect.left+1)/2;
int cy = (vrect.bottom+vrect.top+1)/2;
//Log.d(TAG, "Circles: "+circles+" around ("+cx+","+cy+")");
drawTile(canvas, pcfg, cx, cy, zoom, layer);
if (circles==0)
return;
int xt, yt;
for (int cc=1; cc<=circles; cc++) {
//Log.d(TAG, "cc="+cc);
for (xt=cx-cc; xt<=cx+cc; xt++) {
yt = cy-cc;
//Log.d(TAG, "1: "+xt+","+yt);
if (xt>=vrect.left && xt <= vrect.right && yt >= vrect.top && yt <= vrect.bottom)
drawTile(canvas, pcfg, xt, yt, zoom, layer);
}
for (yt=cy-(cc-1); yt<=cy+cc-1; yt++) {
xt = cx+cc;
//Log.d(TAG, "2: "+xt+","+yt);
if (xt>=vrect.left && xt <= vrect.right && yt >= vrect.top && yt <= vrect.bottom)
drawTile(canvas, pcfg, xt, yt, zoom, layer);
}
for (xt=cx+cc; xt>=cx-cc; xt--) {
yt = cy+cc;
//Log.d(TAG, "3: "+xt+","+yt);
if (xt>=vrect.left && xt <= vrect.right && yt >= vrect.top && yt <= vrect.bottom)
drawTile(canvas, pcfg, xt, yt, zoom, layer);
}
for (yt=cy+cc-1; yt>=cy-(cc-1); yt--) {
xt = cx-cc;
//Log.d(TAG, "4: "+xt+","+yt);
if (xt>=vrect.left && xt <= vrect.right && yt >= vrect.top && yt <= vrect.bottom)
drawTile(canvas, pcfg, xt, yt, zoom, layer);
}
}
//Log.d(TAG, "Tile layer draw finished ");
}
public void drawLegends(Canvas canvas, RectF viewrect, PaintConfig pcfg) {
if (mAttrib != null) {
canvas.drawText(mAttrib, viewrect.centerX()-pcfg.attrib.measureText(mAttrib)/2,
viewrect.centerY()+viewrect.height()*0.4f, pcfg.attrib);
}
}
protected abstract String getTileId(int xt, int yt, int zoom);
protected abstract OsmTile createTile(int xt, int yt, int zoom);
protected abstract void handleMissingTile(OsmTile t, int layer);
protected void drawTile(Canvas canvas, PaintConfig pcfg, int xt, int yt, int zoom, int layer) {
//Log.d(TAG, "Draw tile: "+xt+","+yt+" zoom="+zoom);
String tid = getTileId(xt, yt, zoom);
OsmTile t = mTiles.get(tid);
if (t == null) {
t = createTile(xt, yt, zoom);
mTiles.put(tid, t);
//Log.d(TAG, "New tile, TID="+tid+" LruCache size="+mTiles.size());
handleMissingTile(t, layer);
t.drawX(canvas, pcfg);
} else {
if (! t.draw(canvas, pcfg)) {
t.drawX(canvas, pcfg);
}
}
}
// private void drawTileCoords(Canvas canvas, PaintConfig pcfg, OsmTile t) {
// String st = "";
// st.format("%d,%d,%d", t.mX, t.mY, t.mZoom);
// t.drawText(canvas, pcfg.paint, st);
// }
protected abstract void downloadTile(OsmTile t);
protected int getZoom(PaintConfig pcfg) {
return view2OsmZoom(pcfg.mScale);
}
// Convert from internal view scale value to OSM zoom levels
protected int view2OsmZoom(float scale) {
int zoom = (int) (16+(1.0+Math.log((double)scale)/Math.log(2.0)));
if (zoom > OsmTile.MAX_ZOOM)
zoom = OsmTile.MAX_ZOOM;
//Log.d(TAG, "Scale="+scale+" OsmZoom="+zoom);
return zoom;
}
public void onTrimMemory(int level) {
if (level == ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
mTiles.trimToSize(mTiles.maxSize()/2);
} else if (level == ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
mTiles.trimToSize(0);
}
}
public int getMemorySize() {
return mTiles.size();
}
public void flushCache() {
mTiles.evictAll();
}
protected int getNumLayers() {
return 1;
}
// Attribute, like OSM data attribution
public void setAttrib(String attrib) {
mAttrib = attrib;
}
protected class TileLruCache extends LruCache<String, OsmTile> {
public TileLruCache(int maxSize) {
super(maxSize);
}
protected int sizeOf(String k, OsmTile v) {
return v.getByteSize();
}
};
}