add downloader for tile
git-svn-id: https://osmand.googlecode.com/svn/trunk@25 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
parent
fcaecf9d63
commit
76b36291bb
10 changed files with 605 additions and 173 deletions
8
DataExtractionOSM/logging.properties
Normal file
8
DataExtractionOSM/logging.properties
Normal file
|
@ -0,0 +1,8 @@
|
|||
.level = ERROR
|
||||
handlers=java.util.logging.ConsoleHandler
|
||||
|
||||
# Set the default logging level for the logger named com.mycompany
|
||||
com.osmand.level = ALL
|
||||
|
||||
java.util.logging.ConsoleHandler.level=ALL
|
||||
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
|
|
@ -1,9 +1,19 @@
|
|||
package com.osmand;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Basic algorithms that are not in jdk
|
||||
*/
|
||||
public class Algoritms {
|
||||
private static final int BUFFER_SIZE = 1024;
|
||||
private static final Log log = LogFactory.getLog(Algoritms.class);
|
||||
|
||||
public static boolean isEmpty(String s){
|
||||
return s == null || s.length() == 0;
|
||||
|
@ -18,4 +28,22 @@ public class Algoritms {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static void streamCopy(InputStream in, OutputStream out) throws IOException{
|
||||
byte[] b = new byte[BUFFER_SIZE];
|
||||
int read;
|
||||
while ((read = in.read(b)) != -1) {
|
||||
out.write(b, 0, read);
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeStream(Closeable stream){
|
||||
try {
|
||||
if(stream != null){
|
||||
stream.close();
|
||||
}
|
||||
} catch(IOException e){
|
||||
log.warn("Closing stream warn", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.osmand;
|
|||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.MenuBar;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
|
@ -427,7 +428,9 @@ public class DataExtraction implements IMapLocationListener {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
MenuBar bar = new MenuBar();
|
||||
bar.add(MapPanel.getMenuToChooseSource(mapPanel));
|
||||
frame.setMenuBar(bar);
|
||||
frame.setSize(1024, 768);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
|
|
@ -1,16 +1,42 @@
|
|||
package com.osmand;
|
||||
|
||||
import com.osmand.map.ITileSource;
|
||||
import com.osmand.map.TileSourceManager;
|
||||
|
||||
/**
|
||||
* This is temp class where all path & machine specific properties are written
|
||||
*/
|
||||
public abstract class DefaultLauncherConstants {
|
||||
|
||||
// External files
|
||||
public static String pathToTestDataDir = "E:\\Information\\OSM maps\\";
|
||||
|
||||
public static String pathToOsmFile = pathToTestDataDir + "minsk.osm";
|
||||
public static String pathToOsmBz2File = pathToTestDataDir + "belarus_2010_04_01.osm.bz2";
|
||||
|
||||
public static String pathToDirWithTiles = pathToTestDataDir +"MinskTiles";
|
||||
|
||||
public static String writeTestOsmFile = "C:\\1_tmp.osm"; // could be null - wo writing
|
||||
|
||||
// Initial map settings
|
||||
public static double MAP_startMapLongitude = 27.56;
|
||||
public static double MAP_startMapLatitude = 53.9;
|
||||
public static int MAP_startMapZoom = 15;
|
||||
public static int MAP_divNonLoadedImage = 8;
|
||||
public static boolean loadMissingImages = true;
|
||||
public static ITileSource MAP_defaultTileSource = TileSourceManager.getMapnikSource();
|
||||
|
||||
|
||||
// Application constants
|
||||
public static String APP_NAME = "OsmAnd";
|
||||
public static String APP_VERSION = "0.1";
|
||||
|
||||
|
||||
// Download manager tile settings
|
||||
public static int TILE_DOWNLOAD_THREADS = 4;
|
||||
public static int TILE_DOWNLOAD_SECONTS_TO_WORK = 25;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -5,25 +5,25 @@ import java.awt.Color;
|
|||
import java.awt.Container;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.Menu;
|
||||
import java.awt.MenuBar;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.UnknownHostException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageIO;
|
||||
|
@ -35,15 +35,38 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.osmand.DataExtraction.ExitListener;
|
||||
import com.osmand.MapTileDownloader.DownloadRequest;
|
||||
import com.osmand.MapTileDownloader.IMapDownloaderCallback;
|
||||
import com.osmand.data.DataTileManager;
|
||||
import com.osmand.map.ITileSource;
|
||||
import com.osmand.map.TileSourceManager;
|
||||
import com.osmand.map.TileSourceManager.TileSourceTemplate;
|
||||
import com.osmand.osm.LatLon;
|
||||
import com.osmand.osm.MapUtils;
|
||||
|
||||
public class MapPanel extends JPanel {
|
||||
public class MapPanel extends JPanel implements IMapDownloaderCallback {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Log log = LogFactory.getLog(MapPanel.class);
|
||||
protected static final Log log = LogFactory.getLog(MapPanel.class);
|
||||
|
||||
public static Menu getMenuToChooseSource(final MapPanel panel){
|
||||
Menu tiles = new Menu("Source tile");
|
||||
List<TileSourceTemplate> list = TileSourceManager.getKnownSourceTemplates();
|
||||
for(final TileSourceTemplate l : list){
|
||||
MenuItem menuItem = new MenuItem(l.getName());
|
||||
menuItem.addActionListener(new ActionListener(){
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
panel.setMapName(l);
|
||||
}
|
||||
|
||||
});
|
||||
tiles.add(menuItem);
|
||||
}
|
||||
|
||||
return tiles;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
@ -62,32 +85,32 @@ public class MapPanel extends JPanel {
|
|||
|
||||
content.add(panel, BorderLayout.CENTER);
|
||||
|
||||
MenuBar bar = new MenuBar();
|
||||
bar.add(getMenuToChooseSource(panel));
|
||||
frame.setMenuBar(bar);
|
||||
frame.setSize(512, 512);
|
||||
frame.setVisible(true);
|
||||
|
||||
}
|
||||
|
||||
private File tilesLocation = null;
|
||||
|
||||
// name of source map
|
||||
private String map = "Mapnik";
|
||||
private ITileSource map = DefaultLauncherConstants.MAP_defaultTileSource;
|
||||
|
||||
// tile size of map
|
||||
private final int tileSize = 256;
|
||||
|
||||
// file name with tiles
|
||||
private final File fileWithTiles;
|
||||
|
||||
// special points to draw
|
||||
private DataTileManager<LatLon> points;
|
||||
|
||||
// zoom levle
|
||||
private int zoom = 15;
|
||||
// zoom level
|
||||
private int zoom = DefaultLauncherConstants.MAP_startMapZoom;
|
||||
|
||||
// degree measurements (-180, 180)
|
||||
// долгота
|
||||
private double longitude = 27.56;
|
||||
private double longitude = DefaultLauncherConstants.MAP_startMapLongitude;
|
||||
// широта
|
||||
// degree measurements (90, -90)
|
||||
private double latitude = 53.9;
|
||||
private double latitude = DefaultLauncherConstants.MAP_startMapLatitude;
|
||||
|
||||
private List<IMapLocationListener> listeners = new ArrayList<IMapLocationListener>();
|
||||
|
||||
|
@ -97,15 +120,23 @@ public class MapPanel extends JPanel {
|
|||
private int yStartingImage = 0;
|
||||
private List<Point> pointsToDraw = new ArrayList<Point>();
|
||||
|
||||
private AsyncLoadTileThread autoThread = new AsyncLoadTileThread();
|
||||
private MapTileDownloader downloader = MapTileDownloader.getInstance();
|
||||
Map<String, Image> cache = new HashMap<String, Image>();
|
||||
|
||||
|
||||
|
||||
public MapPanel(File fileWithTiles) {
|
||||
this.fileWithTiles = fileWithTiles;
|
||||
autoThread.start();
|
||||
initUI();
|
||||
tilesLocation = fileWithTiles;
|
||||
downloader.setDownloaderCallback(this);
|
||||
setFocusable(true);
|
||||
addComponentListener(new ComponentAdapter(){
|
||||
public void componentResized(ComponentEvent e) {
|
||||
prepareImage();
|
||||
}
|
||||
});
|
||||
MapMouseAdapter mouse = new MapMouseAdapter();
|
||||
addMouseListener(mouse);
|
||||
addMouseMotionListener(mouse);
|
||||
}
|
||||
|
||||
|
||||
|
@ -117,176 +148,99 @@ public class MapPanel extends JPanel {
|
|||
return MapUtils.getTileNumberY(zoom, latitude);
|
||||
}
|
||||
|
||||
public int getTileSize(){
|
||||
return map == null ? 256 : map.getTileSize();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
|
||||
if (images != null) {
|
||||
for (int i = 0; i < images.length; i++) {
|
||||
for (int j = 0; j < images[i].length; j++) {
|
||||
if(images[i][j] == null){
|
||||
int div = 4;
|
||||
int tileDiv = tileSize / div;
|
||||
for(int k1 = 0; k1 < div; k1++){
|
||||
for(int k2 = 0; k2 < div; k2++){
|
||||
if (images[i][j] == null) {
|
||||
int div = DefaultLauncherConstants.MAP_divNonLoadedImage;
|
||||
int tileDiv = getTileSize() / div;
|
||||
for (int k1 = 0; k1 < div; k1++) {
|
||||
for (int k2 = 0; k2 < div; k2++) {
|
||||
if ((k1 + k2) % 2 == 0) {
|
||||
g.setColor(Color.gray);
|
||||
} else {
|
||||
g.setColor(Color.white);
|
||||
}
|
||||
g.fillRect(i * tileSize+xStartingImage + k1*tileDiv,
|
||||
j * tileSize + yStartingImage + k2*tileDiv, tileDiv, tileDiv);
|
||||
g.fillRect(i * getTileSize() + xStartingImage + k1 * tileDiv, j * getTileSize() + yStartingImage + k2
|
||||
* tileDiv, tileDiv, tileDiv);
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g.drawImage(images[i][j], i * tileSize+xStartingImage, j * tileSize + yStartingImage, this);
|
||||
g.drawImage(images[i][j], i * getTileSize() + xStartingImage, j * getTileSize() + yStartingImage, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g.setColor(Color.black);
|
||||
// draw user points
|
||||
for(Point p : pointsToDraw){
|
||||
for (Point p : pointsToDraw) {
|
||||
g.drawOval(p.x, p.y, 3, 3);
|
||||
g.fillOval(p.x, p.y, 3, 3);
|
||||
}
|
||||
|
||||
String s = MessageFormat.format("Lat : {0}, lon : {1}, zoom : {2}",latitude, longitude, zoom);
|
||||
String s = MessageFormat.format("Lat : {0}, lon : {1}, zoom : {2}", latitude, longitude, zoom);
|
||||
g.drawString(s, 5, 20);
|
||||
|
||||
|
||||
g.fillOval(getWidth()/2 - 2, getHeight()/2 -2, 4, 4);
|
||||
g.drawOval(getWidth()/2 - 2, getHeight()/2 -2, 4, 4);
|
||||
g.drawOval(getWidth()/2 - 5, getHeight()/2 -5, 10, 10);
|
||||
}
|
||||
|
||||
public String getFile(int zoom, int x, int y){
|
||||
return map +"/"+zoom+"/"+(x) +"/"+y+".png";
|
||||
g.fillOval(getWidth() / 2 - 2, getHeight() / 2 - 2, 4, 4);
|
||||
g.drawOval(getWidth() / 2 - 2, getHeight() / 2 - 2, 4, 4);
|
||||
g.drawOval(getWidth() / 2 - 5, getHeight() / 2 - 5, 10, 10);
|
||||
}
|
||||
|
||||
|
||||
public Image getImageFor(int x, int y) throws IOException{
|
||||
String file = getFile(zoom, x, y);
|
||||
|
||||
public String getFileForImage (int x, int y, int zoom){
|
||||
return map.getName() +"/"+zoom+"/"+(x) +"/"+y+".png";
|
||||
}
|
||||
|
||||
public Image getImageFor(int x, int y, int zoom) throws IOException{
|
||||
if(map == null){
|
||||
return null;
|
||||
}
|
||||
String file = getFileForImage(x, y, zoom);
|
||||
if(!cache.containsKey(file)){
|
||||
// ZipEntry en = fileWithTiles.getEntry(file);
|
||||
File en = new File(fileWithTiles, file);
|
||||
File en = new File(tilesLocation, file);
|
||||
if(cache.size() > 1000){
|
||||
ArrayList<String> list = new ArrayList<String>(cache.keySet());
|
||||
for(int i=0; i<list.size(); i+=2){
|
||||
cache.remove(list.get(i));
|
||||
}
|
||||
}
|
||||
// if(en != null){
|
||||
if(en.exists()){
|
||||
// cache.put(file, ImageIO.read(fileWithTiles.getInputStream(en)));
|
||||
long time = System.currentTimeMillis();
|
||||
try {
|
||||
cache.put(file, ImageIO.read(en));
|
||||
System.out.println("Loaded " + (System.currentTimeMillis() - time));
|
||||
} else {
|
||||
autoThread.requestTileToLoad(zoom, x, y);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cache.get(file);
|
||||
}
|
||||
|
||||
public void loadImage(int zoom, int x, int y){
|
||||
try {
|
||||
Image img = null;
|
||||
File en = new File(fileWithTiles, getFile(zoom, x, y));
|
||||
URL url = new URL("http://tile.openstreetmap.org/" + zoom + "/" + x + "/" + y + ".png");
|
||||
en.getParentFile().mkdirs();
|
||||
try {
|
||||
ImageIO.setUseCache(true);
|
||||
javax.imageio.ImageIO.setCacheDirectory(en.getParentFile());
|
||||
} catch (Exception e) {
|
||||
log.warn("cannot set ImageIO cache-directory to " + en.getParent(), e);
|
||||
}
|
||||
try {
|
||||
URLConnection connection = url.openConnection();
|
||||
connection.setRequestProperty("User-Agent", "osmand TilePainter/0.1");
|
||||
img = javax.imageio.ImageIO.read(connection.getInputStream());
|
||||
} catch (UnknownHostException e) {
|
||||
log.info("UnknownHostException, cannot download tile " + url.toExternalForm());
|
||||
} catch (IIOException e) {
|
||||
if (e.getCause() != null && e.getCause() instanceof UnknownHostException) {
|
||||
log.info("UnknownHostException, cannot download tile " + url.toExternalForm(), e);
|
||||
} else {
|
||||
log.warn("cannot download tile " + url.toExternalForm(), e);
|
||||
}
|
||||
}
|
||||
cache.put(getFile(zoom, x, y), img);
|
||||
if (img != null) {
|
||||
try {
|
||||
ImageIO.write((RenderedImage) img, "png", en);
|
||||
} catch (IOException e) {
|
||||
log.warn("cannot save img to " + en.getAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("cannot download pre-rendered tile [" + e.getClass().getSimpleName() + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class AsyncLoadTileThread extends Thread {
|
||||
Stack<TileIndex> tilesToLoad = new Stack<TileIndex>();
|
||||
private class TileIndex {
|
||||
int zoom;
|
||||
int x;
|
||||
int y;
|
||||
}
|
||||
|
||||
public AsyncLoadTileThread() {
|
||||
super("AsyncLoadingTiles");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
synchronized (this) {
|
||||
wait();
|
||||
}
|
||||
while (!tilesToLoad.isEmpty()) {
|
||||
TileIndex p = tilesToLoad.pop();
|
||||
if (cache.get(getFile(p.zoom, p.x, p.y)) == null) {
|
||||
loadImage(p.zoom, p.x, p.y);
|
||||
// TODO dead cycle (causes cancelAllPreviousTile)
|
||||
prepareImage();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
public void tileDownloaded(String dowloadedUrl, DownloadRequest fileSaved) {
|
||||
prepareImage(false);
|
||||
}
|
||||
|
||||
public void cancelAllPreviousTile(){
|
||||
tilesToLoad.clear();
|
||||
}
|
||||
|
||||
public void requestTileToLoad(int zoom, int x, int y){
|
||||
synchronized (this) {
|
||||
TileIndex ind = new TileIndex();
|
||||
ind.zoom = zoom;
|
||||
ind.x = x;
|
||||
ind.y = y;
|
||||
tilesToLoad.add(ind);
|
||||
notify();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO async loading images (show busy cursor while it is loaded)
|
||||
public void prepareImage(){
|
||||
try {
|
||||
prepareImage(DefaultLauncherConstants.loadMissingImages);
|
||||
}
|
||||
|
||||
public void prepareImage(boolean loadNecessaryImages){
|
||||
try {
|
||||
int tileSize = getTileSize();
|
||||
if (images != null) {
|
||||
for (int i = 0; i < images.length; i++) {
|
||||
for (int j = 0; j < images[i].length; j++) {
|
||||
|
@ -303,13 +257,24 @@ public class MapPanel extends JPanel {
|
|||
xStartingImage = -(int) ((xTileLeft - Math.floor(xTileLeft)) * tileSize);
|
||||
yStartingImage = -(int) ((yTileUp - Math.floor(yTileUp)) * tileSize);
|
||||
|
||||
autoThread.cancelAllPreviousTile();
|
||||
if(loadNecessaryImages){
|
||||
downloader.refuseAllPreviousRequests();
|
||||
}
|
||||
int tileXCount = ((int) xTileRight - (int) xTileLeft + 1);
|
||||
int tileYCount = ((int) yTileDown - (int) yTileUp + 1);
|
||||
images = new BufferedImage[tileXCount][tileYCount];
|
||||
for (int i = 0; i < images.length; i++) {
|
||||
for (int j = 0; j < images[i].length; j++) {
|
||||
images[i][j] = getImageFor((int) xTileLeft + i, (int) yTileUp + j);
|
||||
int x= (int) xTileLeft + i;
|
||||
int y = (int) yTileUp + j;
|
||||
images[i][j] = getImageFor(x, y, zoom);
|
||||
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))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,19 +302,6 @@ public class MapPanel extends JPanel {
|
|||
|
||||
|
||||
|
||||
private void initUI() {
|
||||
setFocusable(true);
|
||||
addComponentListener(new ComponentAdapter(){
|
||||
public void componentResized(ComponentEvent e) {
|
||||
prepareImage();
|
||||
}
|
||||
});
|
||||
MapMouseAdapter mouse = new MapMouseAdapter();
|
||||
addMouseListener(mouse);
|
||||
addMouseMotionListener(mouse);
|
||||
}
|
||||
|
||||
|
||||
public void setZoom(int zoom){
|
||||
this.zoom = zoom;
|
||||
prepareImage();
|
||||
|
@ -374,11 +326,11 @@ public class MapPanel extends JPanel {
|
|||
return zoom;
|
||||
}
|
||||
|
||||
public String getMap(){
|
||||
public ITileSource getMap(){
|
||||
return map;
|
||||
}
|
||||
|
||||
public void setMapName(String map){
|
||||
public void setMapName(ITileSource map){
|
||||
this.map = map;
|
||||
prepareImage();
|
||||
}
|
||||
|
@ -422,12 +374,12 @@ public class MapPanel extends JPanel {
|
|||
}
|
||||
if(e.getID() == KeyEvent.KEY_TYPED){
|
||||
if(e.getKeyChar() == '+'){
|
||||
if(zoom < 18){
|
||||
if(zoom < map.getMaximumZoomSupported()){
|
||||
zoom ++;
|
||||
processed = true;
|
||||
}
|
||||
} else if(e.getKeyChar() == '-'){
|
||||
if(zoom > 1){
|
||||
if(zoom > map.getMinimumZoomSupported()){
|
||||
zoom --;
|
||||
processed = true;
|
||||
}
|
||||
|
@ -461,8 +413,8 @@ public class MapPanel extends JPanel {
|
|||
}
|
||||
|
||||
public void dragTo(Point p){
|
||||
double dx = (startDragging.x - (double)p.x)/tileSize;
|
||||
double dy = (startDragging.y - (double)p.y)/tileSize;
|
||||
double dx = (startDragging.x - (double)p.x)/getTileSize();
|
||||
double dy = (startDragging.y - (double)p.y)/getTileSize();
|
||||
double lat = MapUtils.getLatitudeFromTile(zoom, getYTile() + dy);
|
||||
double lon = MapUtils.getLongitudeFromTile(zoom, getXTile() + dx);
|
||||
setLatLon(lat, lon);
|
||||
|
|
158
DataExtractionOSM/src/com/osmand/MapTileDownloader.java
Normal file
158
DataExtractionOSM/src/com/osmand/MapTileDownloader.java
Normal file
|
@ -0,0 +1,158 @@
|
|||
package com.osmand;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
public class MapTileDownloader {
|
||||
|
||||
private static MapTileDownloader downloader = null;
|
||||
private static Log log = LogFactory.getLog(MapTileDownloader.class);
|
||||
|
||||
private ThreadPoolExecutor threadPoolExecutor;
|
||||
private IMapDownloaderCallback callback;
|
||||
private Map<String, DownloadRequest> requestsToLoad;
|
||||
|
||||
|
||||
public static MapTileDownloader getInstance(){
|
||||
if(downloader == null){
|
||||
downloader = new MapTileDownloader(DefaultLauncherConstants.TILE_DOWNLOAD_THREADS);
|
||||
}
|
||||
return downloader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for map downloader
|
||||
*/
|
||||
public interface IMapDownloaderCallback {
|
||||
|
||||
public void tileDownloaded(String dowloadedUrl, DownloadRequest fileSaved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download request could subclassed to create own detailed request
|
||||
*/
|
||||
public static class DownloadRequest {
|
||||
public final File fileToSave;
|
||||
public final int zoom;
|
||||
public final int xTile;
|
||||
public final int yTile;
|
||||
|
||||
public DownloadRequest(File fileToSave, int xTile, int yTile, int zoom) {
|
||||
this.fileToSave = fileToSave;
|
||||
this.xTile = xTile;
|
||||
this.yTile = yTile;
|
||||
this.zoom = zoom;
|
||||
}
|
||||
|
||||
public DownloadRequest(File fileToSave) {
|
||||
this.fileToSave = fileToSave;
|
||||
xTile = -1;
|
||||
yTile = -1;
|
||||
zoom = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public MapTileDownloader(int numberOfThreads){
|
||||
threadPoolExecutor = new ThreadPoolExecutor(1, numberOfThreads, DefaultLauncherConstants.TILE_DOWNLOAD_SECONTS_TO_WORK,
|
||||
TimeUnit.SECONDS, new PriorityBlockingQueue<Runnable>());
|
||||
requestsToLoad = Collections.synchronizedMap(new LinkedHashMap<String, DownloadRequest>());
|
||||
|
||||
}
|
||||
|
||||
public void setDownloaderCallback(IMapDownloaderCallback callback){
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public IMapDownloaderCallback getDownloaderCallback() {
|
||||
return callback;
|
||||
}
|
||||
|
||||
|
||||
public void refuseAllPreviousRequests(){
|
||||
requestsToLoad.clear();
|
||||
}
|
||||
|
||||
public void requestToDownload(String url, DownloadRequest request){
|
||||
requestsToLoad.put(url, request);
|
||||
threadPoolExecutor.execute(new DownloadMapWorker(url, request));
|
||||
}
|
||||
|
||||
|
||||
private class DownloadMapWorker implements Runnable, Comparable<DownloadMapWorker> {
|
||||
private long time = System.currentTimeMillis();
|
||||
private final String downloadUrl;
|
||||
private DownloadRequest request;
|
||||
|
||||
private DownloadMapWorker(String downloadUrl, DownloadRequest request){
|
||||
this.downloadUrl = downloadUrl;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (requestsToLoad) {
|
||||
if(!requestsToLoad.containsKey(downloadUrl)){
|
||||
return;
|
||||
}
|
||||
request = requestsToLoad.remove(downloadUrl);
|
||||
}
|
||||
|
||||
try {
|
||||
URL url = new URL(downloadUrl);
|
||||
// if(log.isDebugEnabled()){
|
||||
log.debug("Downloading tile : " + downloadUrl);
|
||||
// }
|
||||
URLConnection connection = url.openConnection();
|
||||
connection.setRequestProperty("User-Agent", DefaultLauncherConstants.APP_NAME+"/"+DefaultLauncherConstants.APP_VERSION);
|
||||
BufferedInputStream inputStream = new BufferedInputStream(connection.getInputStream(), 8 * 1024);
|
||||
try {
|
||||
if(request != null && request.fileToSave != null){
|
||||
request.fileToSave.getParentFile().mkdirs();
|
||||
FileOutputStream stream = new FileOutputStream(request.fileToSave);
|
||||
try {
|
||||
Algoritms.streamCopy(inputStream, stream);
|
||||
} finally {
|
||||
Algoritms.closeStream(stream);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Algoritms.closeStream(inputStream);
|
||||
}
|
||||
if(log.isDebugEnabled()){
|
||||
log.debug("Downloading tile : " + downloadUrl + " successfull");
|
||||
}
|
||||
if(callback != null){
|
||||
callback.tileDownloaded(downloadUrl, request);
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
log.error("UnknownHostException, cannot download tile " + downloadUrl, e);
|
||||
} catch (IOException e) {
|
||||
log.warn("Cannot download tile : " + downloadUrl, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(DownloadMapWorker o) {
|
||||
return (int) (time - o.time);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
18
DataExtractionOSM/src/com/osmand/map/ITileSource.java
Normal file
18
DataExtractionOSM/src/com/osmand/map/ITileSource.java
Normal file
|
@ -0,0 +1,18 @@
|
|||
package com.osmand.map;
|
||||
|
||||
|
||||
public interface ITileSource {
|
||||
|
||||
public int getMaximumZoomSupported();
|
||||
|
||||
public String getName();
|
||||
|
||||
public int getTileSize();
|
||||
|
||||
public String getUrlToLoad(int x, int y, int zoom);
|
||||
|
||||
public int getMinimumZoomSupported();
|
||||
|
||||
public String getTileFormat();
|
||||
|
||||
}
|
121
DataExtractionOSM/src/com/osmand/map/TileSourceManager.java
Normal file
121
DataExtractionOSM/src/com/osmand/map/TileSourceManager.java
Normal file
|
@ -0,0 +1,121 @@
|
|||
package com.osmand.map;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
public class TileSourceManager {
|
||||
|
||||
public static class TileSourceTemplate implements ITileSource {
|
||||
private int maxZoom;
|
||||
private int minZoom;
|
||||
private String name;
|
||||
private int tileSize;
|
||||
private String urlToLoad;
|
||||
private String ext;
|
||||
private int avgSize;
|
||||
|
||||
public TileSourceTemplate(String name, String urlToLoad, String ext, int maxZoom, int minZoom, int tileSize, int avgSize) {
|
||||
this.maxZoom = maxZoom;
|
||||
this.minZoom = minZoom;
|
||||
this.name = name;
|
||||
this.tileSize = tileSize;
|
||||
this.urlToLoad = urlToLoad;
|
||||
this.ext = ext;
|
||||
this.avgSize = avgSize;
|
||||
}
|
||||
|
||||
|
||||
public int getAverageSize(){
|
||||
return avgSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumZoomSupported() {
|
||||
return maxZoom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimumZoomSupported() {
|
||||
return minZoom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTileSize() {
|
||||
return tileSize;
|
||||
}
|
||||
|
||||
public String getTileFormat(){
|
||||
return ext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrlToLoad(int x, int y, int zoom) {
|
||||
return MessageFormat.format(urlToLoad, zoom+"", x+"", y+"");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static java.util.List<TileSourceTemplate> list;
|
||||
public static java.util.List<TileSourceTemplate> getKnownSourceTemplates(){
|
||||
if(list == null){
|
||||
list = new ArrayList<TileSourceTemplate>();
|
||||
list.add(getMapnikSource());
|
||||
list.add(getOsmaRenderSource());
|
||||
list.add(getCycleMapSource());
|
||||
// list.add(getAerialMapSource());
|
||||
list.add(getCloudMadeSource());
|
||||
list.add(getOpenPisteMapSource());
|
||||
list.add(getGoogleMapsSource());
|
||||
list.add(getGoogleMapsSatelliteSource());
|
||||
list.add(getGoogleMapsTerrainSource());
|
||||
}
|
||||
return list;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static TileSourceTemplate getMapnikSource(){
|
||||
return new TileSourceTemplate("Mapnik", "http://tile.openstreetmap.org/{0}/{1}/{2}.png", ".png", 18, 1, 256, 18000);
|
||||
}
|
||||
|
||||
public static TileSourceTemplate getOsmaRenderSource(){
|
||||
return new TileSourceTemplate("OsmaRender", "http://tah.openstreetmap.org/Tiles/tile/{0}/{1}/{2}.png", ".png", 17, 1, 256, 18000);
|
||||
}
|
||||
|
||||
public static TileSourceTemplate getCycleMapSource(){
|
||||
return new TileSourceTemplate("CycleMap", "http://b.andy.sandbox.cloudmade.com/tiles/cycle/{0}/{1}/{2}.png", ".png", 17, 0, 256, 18000);
|
||||
}
|
||||
|
||||
public static TileSourceTemplate getAerialMapSource(){
|
||||
return new TileSourceTemplate("OpenAerialMap", "http://tile.openaerialmap.org/tiles/1.0.0/openaerialmap-900913/{0}/{1}/{2}.jpg", ".jpg", 13, 0, 256, 18000);
|
||||
}
|
||||
|
||||
public static TileSourceTemplate getCloudMadeSource(){
|
||||
return new TileSourceTemplate("Cloudmade", "http://tile.cloudmade.com/7ded028e030c5929b28bf823486ce84f/1/256/{0}/{1}/{2}.png", ".png", 18, 0, 256, 18000);
|
||||
}
|
||||
|
||||
public static TileSourceTemplate getOpenPisteMapSource(){
|
||||
return new TileSourceTemplate("OpenPisteMap", "http://openpistemap.org/tiles/contours/{0}/{1}/{2}.png", ".png", 17, 0, 256, 18000);
|
||||
}
|
||||
|
||||
public static TileSourceTemplate getGoogleMapsSource(){
|
||||
return new TileSourceTemplate("GoogleMaps", "http://mt3.google.com/vt/v=w2.97&x={1}&y={2}&z={0}", ".png", 19, 0, 256, 18000);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public static TileSourceTemplate getGoogleMapsTerrainSource(){
|
||||
return new TileSourceTemplate("GoogleMaps Terrain", "http://mt3.google.com/mt/v=w2p.87&x={1}&y={2}&z={0}", ".png", 15, 0, 256, 18000);
|
||||
}
|
||||
|
||||
}
|
|
@ -76,6 +76,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
|
|||
});
|
||||
|
||||
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
|
||||
// service.get
|
||||
service.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
|
||||
}
|
||||
|
||||
|
@ -130,6 +131,18 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
// TODO switch off gps
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
// TODO switch on gps
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void locationChanged(double newLatitude, double newLongitude, Object source) {
|
||||
|
|
105
OsmAnd/src/org/apache/commons/logging/LogFactory.java
Normal file
105
OsmAnd/src/org/apache/commons/logging/LogFactory.java
Normal file
|
@ -0,0 +1,105 @@
|
|||
package org.apache.commons.logging;
|
||||
|
||||
public class LogFactory {
|
||||
public static String TAG = "com.osmand";
|
||||
|
||||
public static Log getLog(Class<?> cl){
|
||||
final String name = cl.getName();
|
||||
return new Log() {
|
||||
@Override
|
||||
public void debug(Object message) {
|
||||
android.util.Log.d(TAG, name + " " + message);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Object message, Throwable t) {
|
||||
android.util.Log.d(TAG, name + " " + message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Object message) {
|
||||
android.util.Log.e(TAG, name + " " + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Object message, Throwable t) {
|
||||
android.util.Log.e(TAG, name + " " + message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatal(Object message) {
|
||||
android.util.Log.e(TAG, name + " " + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatal(Object message, Throwable t) {
|
||||
android.util.Log.e(TAG, name + " " + message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Object message) {
|
||||
android.util.Log.i(TAG, name + " " + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Object message, Throwable t) {
|
||||
android.util.Log.i(TAG, name + " " + message, t);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugEnabled() {
|
||||
return android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorEnabled() {
|
||||
return android.util.Log.isLoggable(TAG, android.util.Log.ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFatalEnabled() {
|
||||
return android.util.Log.isLoggable(TAG, android.util.Log.ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInfoEnabled() {
|
||||
return android.util.Log.isLoggable(TAG, android.util.Log.INFO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTraceEnabled() {
|
||||
return android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWarnEnabled() {
|
||||
return android.util.Log.isLoggable(TAG, android.util.Log.WARN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Object message) {
|
||||
android.util.Log.d(TAG, name + " " + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Object message, Throwable t) {
|
||||
android.util.Log.d(TAG, name + " " + message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Object message) {
|
||||
android.util.Log.w(TAG, name + " " + message);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Object message, Throwable t) {
|
||||
android.util.Log.w(TAG, name + " " + message, t);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue