change format of tile/ enable downloading from internet tiles (for android)

git-svn-id: https://osmand.googlecode.com/svn/trunk@27 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-05-01 23:35:00 +00:00
parent 57475433ec
commit d786dcdd60
11 changed files with 283 additions and 80 deletions

View file

@ -1,4 +1,4 @@
.level = ERROR .level = SEVERE
handlers=java.util.logging.ConsoleHandler handlers=java.util.logging.ConsoleHandler
# Set the default logging level for the logger named com.mycompany # Set the default logging level for the logger named com.mycompany

View file

@ -1,6 +1,7 @@
package com.osmand; package com.osmand;
import java.io.Closeable; import java.io.Closeable;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -46,4 +47,17 @@ public class Algoritms {
log.warn("Closing stream warn", e); log.warn("Closing stream warn", e);
} }
} }
public static void updateAllExistingImgTilesToOsmandFormat(File f){
if(f.isDirectory()){
for(File c : f.listFiles()){
updateAllExistingImgTilesToOsmandFormat(c);
}
} else if(f.getName().endsWith(".png") || f.getName().endsWith(".jpg")){
f.renameTo(new File(f.getAbsolutePath() + ".tile"));
} else if(f.getName().endsWith(".andnav2")) {
f.renameTo(new File(f.getAbsolutePath().substring(0, f.getAbsolutePath().length() - ".andnav2".length()) + ".tile"));
}
}
} }

View file

@ -352,8 +352,10 @@ public class DataExtraction implements IMapLocationListener {
final JTextField textField = new JTextField(); final JTextField textField = new JTextField();
final JButton button = new JButton(); final JButton button = new JButton();
button.setText("Set town"); button.setText("Set town");
panel.add(textField, BorderLayout.CENTER); panel.add(textField, BorderLayout.CENTER);
panel.add(button, BorderLayout.EAST); panel.add(button, BorderLayout.WEST);
content.add(panel, BorderLayout.NORTH); content.add(panel, BorderLayout.NORTH);

View file

@ -24,6 +24,7 @@ public abstract class DefaultLauncherConstants {
public static int MAP_divNonLoadedImage = 8; public static int MAP_divNonLoadedImage = 8;
public static boolean loadMissingImages = true; public static boolean loadMissingImages = true;
public static ITileSource MAP_defaultTileSource = TileSourceManager.getMapnikSource(); public static ITileSource MAP_defaultTileSource = TileSourceManager.getMapnikSource();
public static boolean showGPSCoordinates = true;
// Application constants // Application constants
@ -34,7 +35,7 @@ public abstract class DefaultLauncherConstants {
// Download manager tile settings // Download manager tile settings
public static int TILE_DOWNLOAD_THREADS = 4; public static int TILE_DOWNLOAD_THREADS = 4;
public static int TILE_DOWNLOAD_SECONTS_TO_WORK = 25; public static int TILE_DOWNLOAD_SECONTS_TO_WORK = 25;
public static final int TILE_DOWNLOAD_MAX_ERRORS = -1;

View file

@ -195,17 +195,28 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
} }
public String getFileForImage (int x, int y, int zoom){
return map.getName() +"/"+zoom+"/"+(x) +"/"+y+".png"; public File getTilesLocation() {
return tilesLocation;
} }
public Image getImageFor(int x, int y, int zoom) throws IOException{ public void setTilesLocation(File tilesLocation) {
this.tilesLocation = tilesLocation;
prepareImage();
}
public String getFileForImage (int x, int y, int zoom, String ext){
return map.getName() +"/"+zoom+"/"+(x) +"/"+y+ext+".tile";
}
public Image getImageFor(int x, int y, int zoom, boolean loadIfNeeded) throws IOException{
if(map == null){ if(map == null){
return null; return null;
} }
String file = getFileForImage(x, y, zoom); String file = getFileForImage(x, y, zoom, map.getTileFormat());
if(!cache.containsKey(file)){ if(cache.get(file) == null){
File en = new File(tilesLocation, file); File en = new File(tilesLocation, file);
if(cache.size() > 1000){ if(cache.size() > 1000){
ArrayList<String> list = new ArrayList<String>(cache.keySet()); ArrayList<String> list = new ArrayList<String>(cache.keySet());
@ -213,17 +224,25 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
cache.remove(list.get(i)); cache.remove(list.get(i));
} }
} }
if(en.exists() && !downloader.isFileCurrentlyDownloaded(en)){ if (!downloader.isFileCurrentlyDownloaded(en)) {
long time = System.currentTimeMillis(); if (en.exists()) {
try { long time = System.currentTimeMillis();
cache.put(file, ImageIO.read(en)); try {
if(log.isDebugEnabled()){ cache.put(file, ImageIO.read(en));
log.debug("Loaded file : " + file + " " + -(time -System.currentTimeMillis())+" ms"); if (log.isDebugEnabled()) {
log.debug("Loaded file : " + file + " " + -(time - System.currentTimeMillis()) + " ms");
}
} catch (IIOException e) {
log.error("Eror reading png " + x + " " + y + " zoom : " + zoom, e);
}
}
if(loadIfNeeded && cache.get(file) == null){
String urlToLoad = map.getUrlToLoad(x, y, zoom);
if (urlToLoad != null) {
downloader.requestToDownload(urlToLoad, new DownloadRequest(en, x, y, zoom));
} }
} catch (IIOException e) {
log.error("Eror reading png " + x +" " + y + " zoom : " + zoom, e);
} }
} }
} }
return cache.get(file); return cache.get(file);
@ -239,7 +258,7 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
if(request.zoom == this.zoom && if(request.zoom == this.zoom &&
(i >=0 && i<images.length) && (j>=0 && j< images[i].length)){ (i >=0 && i<images.length) && (j>=0 && j< images[i].length)){
try { try {
images[i][j] = getImageFor(request.xTile, request.yTile, zoom); images[i][j] = getImageFor(request.xTile, request.yTile, zoom, false);
repaint(); repaint();
} catch (IOException e) { } catch (IOException e) {
log.error("Eror reading png " + request.xTile +" " + request.yTile + " zoom : " + zoom, e); log.error("Eror reading png " + request.xTile +" " + request.yTile + " zoom : " + zoom, e);
@ -281,15 +300,7 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
for (int j = 0; j < images[i].length; j++) { for (int j = 0; j < images[i].length; j++) {
int x= (int) xTileLeft + i; int x= (int) xTileLeft + i;
int y = (int) yTileUp + j; int y = (int) yTileUp + j;
images[i][j] = getImageFor(x, y, zoom); images[i][j] = getImageFor(x, y, zoom, loadNecessaryImages);
if(loadNecessaryImages && images[i][j] == null && map != null){
String urlToLoad = map.getUrlToLoad(x, y, zoom);
if(urlToLoad != null){
downloader.requestToDownload(urlToLoad,
new DownloadRequest(new File(tilesLocation, getFileForImage(x, y, zoom)),
x, y, zoom));
}
}
} }
} }
@ -347,6 +358,12 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
public void setMapName(ITileSource map){ public void setMapName(ITileSource map){
this.map = map; this.map = map;
if(map.getMaximumZoomSupported() < this.zoom){
zoom = map.getMaximumZoomSupported();
}
if(map.getMinimumZoomSupported() > this.zoom){
zoom = map.getMinimumZoomSupported();
}
prepareImage(); prepareImage();
} }

View file

@ -22,11 +22,16 @@ public class MapTileDownloader {
private static MapTileDownloader downloader = null; private static MapTileDownloader downloader = null;
private static Log log = LogFactory.getLog(MapTileDownloader.class); private static Log log = LogFactory.getLog(MapTileDownloader.class);
private ThreadPoolExecutor threadPoolExecutor; private ThreadPoolExecutor threadPoolExecutor;
private IMapDownloaderCallback callback; private IMapDownloaderCallback callback;
private Set<File> currentlyDownloaded; private Set<File> currentlyDownloaded;
private int currentErrors = 0;
public static MapTileDownloader getInstance(){ public static MapTileDownloader getInstance(){
if(downloader == null){ if(downloader == null){
@ -97,6 +102,11 @@ public class MapTileDownloader {
} }
public void requestToDownload(String url, DownloadRequest request){ public void requestToDownload(String url, DownloadRequest request){
if(DefaultLauncherConstants.TILE_DOWNLOAD_MAX_ERRORS > 0 &&
currentErrors > DefaultLauncherConstants.TILE_DOWNLOAD_MAX_ERRORS){
return;
}
if (!isFileCurrentlyDownloaded(request.fileToSave)) { if (!isFileCurrentlyDownloaded(request.fileToSave)) {
threadPoolExecutor.execute(new DownloadMapWorker(url, request)); threadPoolExecutor.execute(new DownloadMapWorker(url, request));
} }
@ -147,8 +157,10 @@ public class MapTileDownloader {
callback.tileDownloaded(downloadUrl, request); callback.tileDownloaded(downloadUrl, request);
} }
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
currentErrors++;
log.error("UnknownHostException, cannot download tile " + downloadUrl, e); log.error("UnknownHostException, cannot download tile " + downloadUrl, e);
} catch (IOException e) { } catch (IOException e) {
currentErrors++;
log.warn("Cannot download tile : " + downloadUrl, e); log.warn("Cannot download tile : " + downloadUrl, e);
} }
} }

View file

@ -0,0 +1,14 @@
package com.osmand;
/**
* This class is designed to put all to do's and link them with code.
* The whole methods could be paste or just constants.
* Do not worry to put ugly code here (just a little piece)
*
*/
public class ToDoConstants {
public int CONFIG_COMMONS_LOGGING_IN_ANDROID = 1;
}

View file

@ -72,9 +72,12 @@ public class TileSourceManager {
list.add(getCloudMadeSource()); list.add(getCloudMadeSource());
list.add(getOpenPisteMapSource()); list.add(getOpenPisteMapSource());
list.add(getGoogleMapsSource()); list.add(getGoogleMapsSource());
// TODO ? list.add(getGoogleMapsSatelliteSource());
// list.add(getGoogleMapsSatelliteSource()); list.add(getGoogleMapsTerrainSource());
// list.add(getGoogleMapsTerrainSource()); list.add(getMicrosoftMapsSource());
list.add(getMicrosoftEarthSource());
list.add(getMicrosoftHybridSource());
} }
return list; return list;
@ -112,11 +115,74 @@ public class TileSourceManager {
} }
public static TileSourceTemplate getGoogleMapsSatelliteSource(){ public static TileSourceTemplate getGoogleMapsSatelliteSource(){
return new TileSourceTemplate("GoogleMaps Satellite", "http://khm1.google.com/kh/v=37&x={1}&y={2}&z={0}", ".png", 19, 0, 256, 18000); return new TileSourceTemplate("GoogleMaps Satellite", "http://khm1.google.com/kh/v=59&x={1}&y={2}&z={0}", ".jpg", 20, 0, 256, 18000);
} }
public static TileSourceTemplate getGoogleMapsTerrainSource(){ public static TileSourceTemplate getGoogleMapsTerrainSource(){
return new TileSourceTemplate("GoogleMaps Terrain", "http://mt3.google.com/mt/v=w2.87&x={1}&y={2}&z={0}", ".png", 15, 0, 256, 18000); return new TileSourceTemplate("GoogleMaps Terrain", "http://mt3.google.com/vt/v=w2p.111&hl=en&x={1}&y={2}&z={0}", ".jpg", 15, 0, 256, 18000);
} }
public static TileSourceTemplate getMicrosoftMapsSource(){
return new MicrosoftTileSourceTemplate("Microsoft Maps", 'r', "png", ".png", 19, 1, 256, 18000);
}
public static TileSourceTemplate getMicrosoftEarthSource(){
return new MicrosoftTileSourceTemplate("Microsoft Earth", 'a', "jpg", ".jpg", 19, 1, 256, 18000);
}
public static TileSourceTemplate getMicrosoftHybridSource(){
return new MicrosoftTileSourceTemplate("Microsoft Hybrid", 'h', "jpg", ".jpg", 19, 1, 256, 18000);
}
protected static final char[] NUM_CHAR = { '0', '1', '2', '3' };
/**
* See: http://msdn.microsoft.com/en-us/library/bb259689.aspx
* @param zoom
* @param tilex
* @param tiley
* @return quadtree encoded tile number
*
*/
public static String encodeQuadTree(int zoom, int tilex, int tiley) {
char[] tileNum = new char[zoom];
for (int i = zoom - 1; i >= 0; i--) {
// Binary encoding using ones for tilex and twos for tiley. if a bit
// is set in tilex and tiley we get a three.
int num = (tilex % 2) | ((tiley % 2) << 1);
tileNum[i] = NUM_CHAR[num];
tilex >>= 1;
tiley >>= 1;
}
return new String(tileNum);
}
public static class MicrosoftTileSourceTemplate extends TileSourceTemplate {
private final char mapTypeChar;
int serverNum = 0; // 0..3
protected String urlBase = ".ortho.tiles.virtualearth.net/tiles/";
protected String urlAppend = "?g=45";
private final String tileType;
public MicrosoftTileSourceTemplate(String name, char mapTypeChar , String type,
String ext, int maxZoom, int minZoom, int tileSize, int avgSize) {
super(name, null, ext, maxZoom, minZoom, tileSize, avgSize);
this.mapTypeChar = mapTypeChar;
this.tileType = type;
}
@Override
public String getUrlToLoad(int x, int y, int zoom) {
String tileNum = encodeQuadTree(zoom, x, y);
// serverNum = (serverNum + 1) % serverNumMax;
return "http://" + mapTypeChar + serverNum + urlBase + mapTypeChar + tileNum + "."
+ tileType + urlAppend;
}
}
} }

View file

@ -20,4 +20,6 @@
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"></uses-permission> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
</manifest> </manifest>

View file

@ -40,7 +40,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
setContentView(R.layout.main); setContentView(R.layout.main);
mapView = (OsmandMapTileView) findViewById(R.id.View01); mapView = (OsmandMapTileView) findViewById(R.id.View01);
mapView.setFileWithTiles(new File(Environment.getExternalStorageDirectory(), "osmand/tiles/Mapnik")); mapView.setFileWithTiles(new File(Environment.getExternalStorageDirectory(), "osmand/tiles/"));
mapView.addMapLocationListener(this); mapView.addMapLocationListener(this);
ZoomControls zoomControls = (ZoomControls) findViewById(R.id.ZoomControls01); ZoomControls zoomControls = (ZoomControls) findViewById(R.id.ZoomControls01);

View file

@ -2,11 +2,15 @@ package com.osmand;
import java.io.File; import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
@ -15,23 +19,22 @@ import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.PointF; import android.graphics.PointF;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.os.Handler;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import com.osmand.MapTileDownloader.DownloadRequest;
import com.osmand.MapTileDownloader.IMapDownloaderCallback;
import com.osmand.map.ITileSource;
import com.osmand.osm.MapUtils; import com.osmand.osm.MapUtils;
public class OsmandMapTileView extends View { public class OsmandMapTileView extends View implements IMapDownloaderCallback {
protected final int emptyTileDivisor = 4; protected final int emptyTileDivisor = DefaultLauncherConstants.MAP_divNonLoadedImage;
protected final int maxImgCacheSize = 512; protected final int maxImgCacheSize = 512;
protected static final Log log = LogFactory.getLog(OsmandMapTileView.class);
/**
* tile size of map
*/
private int tileSize = 256;
/** /**
* file or directory with tiles * file or directory with tiles
*/ */
@ -40,20 +43,22 @@ public class OsmandMapTileView extends View {
/** /**
* zoom level * zoom level
*/ */
private int zoom = 15; private int zoom = DefaultLauncherConstants.MAP_startMapZoom;
// degree measurements (-180, 180) private double longitude = DefaultLauncherConstants.MAP_startMapLongitude;
// долгота
private double longitude = 27.56; private double latitude = DefaultLauncherConstants.MAP_startMapLatitude;
// широта
// degree measurements (90, -90) // name of source map
private double latitude = 53.9; private ITileSource map = DefaultLauncherConstants.MAP_defaultTileSource;
/** /**
* listeners * listeners
*/ */
private List<IMapLocationListener> listeners = new ArrayList<IMapLocationListener>(); private List<IMapLocationListener> listeners = new ArrayList<IMapLocationListener>();
private MapTileDownloader downloader = MapTileDownloader.getInstance();
// cached data to draw images // cached data to draw images
private Bitmap[][] images; private Bitmap[][] images;
@ -63,10 +68,19 @@ public class OsmandMapTileView extends View {
private int yStartingImage = 0; private int yStartingImage = 0;
Map<String, Bitmap> cacheOfImages = new WeakHashMap<String, Bitmap>(); Map<String, Bitmap> cacheOfImages = new WeakHashMap<String, Bitmap>();
private PointF startDragging = null;
Paint paintGrayFill; Paint paintGrayFill;
Paint paintWhiteFill; Paint paintWhiteFill;
Paint paintBlack; Paint paintBlack;
final Handler mHandler = new Handler();
// Create runnable for posting
final Runnable invalidateView = new Runnable() {
public void run() {
invalidate();
}
};
public OsmandMapTileView(Context context, AttributeSet attrs) { public OsmandMapTileView(Context context, AttributeSet attrs) {
@ -94,14 +108,18 @@ public class OsmandMapTileView extends View {
prepareImage(); prepareImage();
setClickable(true); setClickable(true);
downloader.setDownloaderCallback(this);
} }
public int getTileSize() {
return map == null ? 256 : map.getTileSize();
}
private PointF startDragging = null;
public void dragTo(PointF p){ public void dragTo(PointF p){
double dx = (startDragging.x - (double)p.x)/tileSize; double dx = (startDragging.x - (double)p.x)/getTileSize();
double dy = (startDragging.y - (double)p.y)/tileSize; double dy = (startDragging.y - (double)p.y)/getTileSize();
this.latitude = MapUtils.getLatitudeFromTile(zoom, getYTile() + dy); this.latitude = MapUtils.getLatitudeFromTile(zoom, getYTile() + dy);
this.longitude = MapUtils.getLongitudeFromTile(zoom, getXTile() + dx); this.longitude = MapUtils.getLongitudeFromTile(zoom, getXTile() + dx);
prepareImage(); prepareImage();
@ -138,7 +156,7 @@ public class OsmandMapTileView extends View {
} }
protected void drawEmptyTile(Canvas cvs, int x, int y){ protected void drawEmptyTile(Canvas cvs, int x, int y){
int tileDiv = tileSize / emptyTileDivisor; int tileDiv = getTileSize() / emptyTileDivisor;
for (int k1 = 0; k1 < emptyTileDivisor; k1++) { for (int k1 = 0; k1 < emptyTileDivisor; k1++) {
for (int k2 = 0; k2 < emptyTileDivisor; k2++) { for (int k2 = 0; k2 < emptyTileDivisor; k2++) {
@ -160,21 +178,41 @@ public class OsmandMapTileView extends View {
for (int i = 0; i < images.length; i++) { for (int i = 0; i < images.length; i++) {
for (int j = 0; j < images[i].length; j++) { for (int j = 0; j < images[i].length; j++) {
if (images[i][j] == null) { if (images[i][j] == null) {
drawEmptyTile(canvas, i*tileSize+xStartingImage, j * tileSize + yStartingImage); drawEmptyTile(canvas, i*getTileSize()+xStartingImage, j * getTileSize() + yStartingImage);
} else { } else {
canvas.drawBitmap(images[i][j], i * tileSize + xStartingImage, j * tileSize + yStartingImage, null); canvas.drawBitmap(images[i][j], i * getTileSize() + xStartingImage, j * getTileSize() + yStartingImage, null);
} }
} }
} }
} }
canvas.drawCircle(getWidth()/2, getHeight()/2, 3, paintBlack); canvas.drawCircle(getWidth()/2, getHeight()/2, 3, paintBlack);
canvas.drawCircle(getWidth()/2, getHeight()/2, 6, paintBlack); canvas.drawCircle(getWidth()/2, getHeight()/2, 6, paintBlack);
if (DefaultLauncherConstants.showGPSCoordinates) {
canvas.drawText(MessageFormat.format("Lat : {0}, lon : {1}, zoom : {2}", latitude, longitude, zoom), 0, 15, paintBlack);
}
} }
public Bitmap getImageFor(int x, int y) {
String file = "/" + zoom + "/" + (x) + "/" + y + ".png";
if (!cacheOfImages.containsKey(file) && fileWithTiles != null) { @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
prepareImage();
super.onSizeChanged(w, h, oldw, oldh);
}
public String getFileForImage (int x, int y, int zoom, String ext){
return map.getName() +"/"+zoom+"/"+(x) +"/"+y+ext+".tile";
}
public Bitmap getImageFor(int x, int y, int zoom, boolean loadIfNeeded) {
if (map == null || fileWithTiles == null || !fileWithTiles.canRead()) {
return null;
}
String file = getFileForImage(x, y, zoom, map.getTileFormat());
if (cacheOfImages.get(file) == null) {
File en = new File(fileWithTiles, file); File en = new File(fileWithTiles, file);
if (cacheOfImages.size() > maxImgCacheSize) { if (cacheOfImages.size() > maxImgCacheSize) {
ArrayList<String> list = new ArrayList<String>(cacheOfImages.keySet()); ArrayList<String> list = new ArrayList<String>(cacheOfImages.keySet());
@ -184,39 +222,62 @@ public class OsmandMapTileView extends View {
} }
System.gc(); System.gc();
} }
if (en.exists() && en.canRead()) { if (!downloader.isFileCurrentlyDownloaded(en)) {
cacheOfImages.put(file, BitmapFactory.decodeFile(en.getAbsolutePath())); if (en.exists()) {
} else { long time = System.currentTimeMillis();
cacheOfImages.put(file, null); cacheOfImages.put(file, BitmapFactory.decodeFile(en.getAbsolutePath()));
if (log.isDebugEnabled()) {
log.debug("Loaded file : " + file + " " + -(time - System.currentTimeMillis()) + " ms");
}
}
if(loadIfNeeded && cacheOfImages.get(file) == null){
String urlToLoad = map.getUrlToLoad(x, y, zoom);
if (urlToLoad != null) {
downloader.requestToDownload(urlToLoad, new DownloadRequest(en, x, y, zoom));
}
}
} }
} }
return cacheOfImages.get(file); return cacheOfImages.get(file);
} }
@Override @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) { public void tileDownloaded(String dowloadedUrl, DownloadRequest request) {
prepareImage(); int tileSize = getTileSize();
super.onSizeChanged(w, h, oldw, oldh); double xTileLeft = getXTile() - getWidth() / (2d * tileSize);
double yTileUp = getYTile() - getHeight() / (2d * tileSize);
int i = request.xTile - (int)xTileLeft;
int j = request.yTile - (int)yTileUp;
if(request.zoom == this.zoom &&
(i >= 0 && i < images.length) && (j >= 0 && j < images[i].length)) {
images[i][j] = getImageFor(request.xTile, request.yTile, zoom, false);
mHandler.post(invalidateView);
}
} }
// TODO async loading images (show busy cursor while it is loaded) public void prepareImage(){
public void prepareImage() { prepareImage(DefaultLauncherConstants.loadMissingImages);
double xTileLeft = getXTile() - getWidth() / (2d * tileSize); }
double xTileRight = getXTile() + getWidth() / (2d * tileSize);
double yTileUp = getYTile() - getHeight() / (2d * tileSize); public void prepareImage(boolean loadNecessaryImages) {
double yTileDown = getYTile() + getHeight() / (2d * tileSize); if (loadNecessaryImages) {
downloader.refuseAllPreviousRequests();
}
double xTileLeft = getXTile() - getWidth() / (2d * getTileSize());
double xTileRight = getXTile() + getWidth() / (2d * getTileSize());
double yTileUp = getYTile() - getHeight() / (2d * getTileSize());
double yTileDown = getYTile() + getHeight() / (2d * getTileSize());
xStartingImage = -(int) ((xTileLeft - Math.floor(xTileLeft)) * tileSize); xStartingImage = -(int) ((xTileLeft - Math.floor(xTileLeft)) * getTileSize());
yStartingImage = -(int) ((yTileUp - Math.floor(yTileUp)) * tileSize); yStartingImage = -(int) ((yTileUp - Math.floor(yTileUp)) * getTileSize());
int tileXCount = ((int) xTileRight - (int) xTileLeft + 1); int tileXCount = ((int) xTileRight - (int) xTileLeft + 1);
int tileYCount = ((int) yTileDown - (int) yTileUp + 1); int tileYCount = ((int) yTileDown - (int) yTileUp + 1);
images = new Bitmap[tileXCount][tileYCount]; images = new Bitmap[tileXCount][tileYCount];
for (int i = 0; i < images.length; i++) { for (int i = 0; i < images.length; i++) {
for (int j = 0; j < images[i].length; j++) { for (int j = 0; j < images[i].length; j++) {
images[i][j] = getImageFor((int) xTileLeft + i, (int) yTileUp + j); images[i][j] = getImageFor((int) xTileLeft + i, (int) yTileUp + j, zoom, loadNecessaryImages);
} }
} }
invalidate(); invalidate();
@ -225,14 +286,31 @@ public class OsmandMapTileView extends View {
public void setZoom(int zoom){ public void setZoom(int zoom){
this.zoom = zoom; if (map == null || (map.getMaximumZoomSupported() >= zoom && map.getMinimumZoomSupported() <= zoom)) {
prepareImage(); this.zoom = zoom;
prepareImage();
}
} }
public File getFileWithTiles() { public File getFileWithTiles() {
return fileWithTiles; return fileWithTiles;
} }
public ITileSource getMap() {
return map;
}
public void setMap(ITileSource map) {
this.map = map;
if(map.getMaximumZoomSupported() < this.zoom){
zoom = map.getMaximumZoomSupported();
}
if(map.getMinimumZoomSupported() > this.zoom){
zoom = map.getMinimumZoomSupported();
}
prepareImage();
}
public void setFileWithTiles(File fileWithTiles) { public void setFileWithTiles(File fileWithTiles) {
this.fileWithTiles = fileWithTiles; this.fileWithTiles = fileWithTiles;
prepareImage(); prepareImage();
@ -257,9 +335,6 @@ public class OsmandMapTileView extends View {
return zoom; return zoom;
} }
public int getTileSize() {
return tileSize;
}
public void addMapLocationListener(IMapLocationListener l){ public void addMapLocationListener(IMapLocationListener l){