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

222 lines
7.0 KiB
Java

package dk.network42.osmfocus;
import java.util.ArrayList;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.Log;
import android.view.View;
public class OsmTileLayerVector extends OsmTileLayer {
private static final String TAG = "OsmTileLayerVector";
private static final int TILEZOOM = 16; // Vector tile zoom level
private static final int MAX_POI = 8;
private static final float MIN_SCALE = 0.5f;
String mProviderArg;
SharedData mG;
ArrayList<OsmElement> mNearest = new ArrayList<OsmElement>(MAX_POI);
RectF [] mUsedArea = new RectF[MAX_POI];
boolean filterWayNodes = false;
public OsmTileLayerVector(OsmTileProvider provider, int maxCacheSize) {
super(provider, maxCacheSize);
mProviderArg = "";
}
public void setSharedData(SharedData data) {
mG = data;
}
protected void tryAutoDownload() {
if (mG.mVectorAutoDownload == SharedData.AUTODOWNLOAD_MANUAL)
return;
int xt = OsmTile.lon2tile(mG.mLon, TILEZOOM);
int yt = OsmTile.lat2tile(mG.mLat, TILEZOOM);
int x, y, c=0;
String tid;
if (mG.mVectorAutoDownload == SharedData.AUTODOWNLOAD_AUTOMATIC2)
c=1;
for (x=xt-c; x<=xt+c; x++) {
for (y=yt-c; y<=yt+c; y++) {
tid = OsmTile.tileId(mProviderArg, x, y, TILEZOOM);
OsmTileVector tile = (OsmTileVector) mTiles.get(tid);
if (tile != null && tile.mDb == null && !tile.isQueuedForDownload()) {
downloadTile(tile);
}
}
}
}
protected OsmTile createTile(int xt, int yt, int zoom) {
return new OsmTileVector(xt, yt, zoom);
}
// Called once immediately after createTile()
protected void handleMissingTile(OsmTile t, int layer) {
tryAutoDownload();
}
// Shading are only drawn on layer 1
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);
if (layer==1)
t.drawX(canvas, pcfg);
} else {
if (layer==0) {
t.draw(canvas, pcfg);
}
if (layer==1 && !t.canDraw(canvas, pcfg)) {
t.drawX(canvas, pcfg);
}
}
}
protected void downloadTile(OsmTile t) {
if (t.mDownloadErrs < 2) {
mProvider.downloadTile(mProviderArg, t, mHandler);
} else {
//Log.d(TAG, "Skipping download, errs="+t.mDownloadErrs);
}
}
protected String getTileId(int xt, int yt, int zoom) {
return OsmTile.tileId(mProviderArg, xt, yt, zoom);
}
// See: http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
@Override
protected int view2OsmZoom(float scale) {
return 16;
}
public void download(double lon, double lat) {
int xt = OsmTile.lon2tile(lon, TILEZOOM);
int yt = OsmTile.lat2tile(lat, TILEZOOM);
String tid = OsmTile.tileId(mProviderArg, xt, yt, TILEZOOM);
OsmTile t = mTiles.get(tid);
if (t == null) {
t = createTile(xt, yt, TILEZOOM);
}
downloadTile(t);
}
public int closestElements(double lon, double lat, int max, ArrayList<OsmElement> near) {
near.clear();
int xt = OsmTile.lon2tile(lon, TILEZOOM);
int yt = OsmTile.lat2tile(lat, TILEZOOM);
int x, y, c=1;
String tid;
for (x=xt-c; x<=xt+c; x++) {
for (y=yt-c; y<=yt+c; y++) {
tid = OsmTile.tileId(mProviderArg, x, y, TILEZOOM);
OsmTileVector t = (OsmTileVector) mTiles.get(tid);
if (t != null && t.mDb != null) {
t.mDb.closestElements(lon, lat, max, near);
}
}
}
return near.size();
}
public void draw(Canvas canvas, RectF worldport, PaintConfig pcfg) {
if (pcfg.mScale<MIN_SCALE)
return;
for (int ii=0; ii<getNumLayers(); ii++) { // Sub-layers
drawTiles(canvas, worldport, pcfg, ii);
}
tryAutoDownload();
if (closestElements(mG.mLon, mG.mLat, mG.mPoisToShow, mNearest)==0)
return;
OsmDB.quadSort(mNearest);
//OsmDB.radianSortCW(mNearest, mG.mLon, GeoMath.latToMercator(mG.mLat), 0); //Math.PI*3.0/4.0);
int pos=0;
for (int ii = 0; ii<mNearest.size(); ++ii) {
OsmElement e = mNearest.get(ii);
// if (!filterWayNodes || !((OsmNode)mNearest.get(ii)).mIsWayNode) {
//Log.d(TAG, "Hightlight "+e);
e.mDb.highlightElem(canvas, mG.mPcfg, e, ii);
pos++;
if (pos==mG.mPoisToShow) break;
// }
}
// FIXME: Needs scaling to screen coords
//canvas.drawCircle((float)mG.mLon, (float)GeoMath.latToMercator(mG.mLat),
// (float) mNearest.get(mNearest.size()-1).distTo(mG.mLon, mG.mLat), mG.mPcfg.horizon);
}
private Paint.Align[] xloc4 = {Paint.Align.LEFT, Paint.Align.RIGHT, Paint.Align.LEFT, Paint.Align.RIGHT};
private Paint.Align[] yloc4 = {Paint.Align.LEFT, Paint.Align.LEFT, Paint.Align.RIGHT, Paint.Align.RIGHT};
private Paint.Align[] xloc8 = {Paint.Align.LEFT, Paint.Align.CENTER, Paint.Align.RIGHT, Paint.Align.LEFT, Paint.Align.RIGHT, Paint.Align.LEFT, Paint.Align.CENTER, Paint.Align.RIGHT};
private Paint.Align[] yloc8 = {Paint.Align.LEFT, Paint.Align.LEFT, Paint.Align.LEFT, Paint.Align.CENTER, Paint.Align.CENTER, Paint.Align.RIGHT, Paint.Align.RIGHT, Paint.Align.RIGHT};
public void drawLegends(Canvas canvas, RectF viewrect, PaintConfig pcfg) {
if (pcfg.mScale<MIN_SCALE) {
String txt;
if (pcfg.mBackMapType == MAPTYPE_INTERNAL) {
txt = mG.mCtx.getString(R.string.info_notshowvectoratzoomlevel);
} else {
txt = mG.mCtx.getString(R.string.info_notshowpoiatzoomlevel);
}
canvas.drawText(txt, viewrect.centerX()-mG.mPcfg.debughud.measureText(txt)/2,
viewrect.centerY()-mG.mPcfg.mHUDspacing, mG.mPcfg.debughud);
return;
}
int pos=0;
Paint.Align[] xloc, yloc;
if (mG.mPoisToShow==8) {
xloc = xloc8; yloc = yloc8;
} else {
xloc = xloc4; yloc = yloc4;
}
for (int ii = 0; ii<mNearest.size(); ++ii) {
if (!filterWayNodes || !((OsmNode)mNearest.get(ii)).mIsWayNode) {
mUsedArea[ii] = mNearest.get(ii).drawTags(canvas, viewrect, mG.mShowPoiLines,
xloc[pos], yloc[pos], mG.mPcfg, ii);
pos++;
if (pos==mG.mPoisToShow) break;
}
}
String tid = OsmTile.tileId(mProviderArg, mG.mLon, mG.mLat, TILEZOOM);
OsmTileVector t = (OsmTileVector) mTiles.get(tid);
if (t == null || t.mDb == null) {
//Log.d(TAG, "No focus tile (id="+tid+") at "+mG.mLon+","+mG.mLat);
tryAutoDownload();
String txt;
if (t != null && t.mDownloadErrs > 0) {
txt = mG.mCtx.getString(R.string.info_errdownloadarea);
} else {
if (mG.mVectorAutoDownload==SharedData.AUTODOWNLOAD_MANUAL) {
txt = mG.mCtx.getString(R.string.info_locationoutside);
} else {
txt = mG.mCtx.getString(R.string.info_downloading);
}
}
canvas.drawText(txt, viewrect.centerX()-mG.mPcfg.debughud.measureText(txt)/2,
viewrect.centerY()-mG.mPcfg.mHUDspacing, mG.mPcfg.debughud);
}
}
protected int getNumLayers() {
return 2; // Vector and shaded
}
}