From fcaecf9d63080443a9975f67752fa1ea018e2465 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Thu, 29 Apr 2010 22:47:07 +0000 Subject: [PATCH] add ability to download tiles from internet git-svn-id: https://osmand.googlecode.com/svn/trunk@22 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8 --- .../src/com/osmand/DataExtraction.java | 24 ++- .../src/com/osmand/MapPanel.java | 183 ++++++++++++++---- .../src/com/osmand/data/Region.java | 1 + .../src/com/osmand/osm/OSMSettings.java | 3 +- OsmAnd/AndroidManifest.xml | 3 +- OsmAnd/src/com/osmand/MapActivity.java | 12 +- 6 files changed, 178 insertions(+), 48 deletions(-) diff --git a/DataExtractionOSM/src/com/osmand/DataExtraction.java b/DataExtractionOSM/src/com/osmand/DataExtraction.java index 4613778502..a72374ebf8 100644 --- a/DataExtractionOSM/src/com/osmand/DataExtraction.java +++ b/DataExtractionOSM/src/com/osmand/DataExtraction.java @@ -12,6 +12,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -42,6 +43,7 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.stream.XMLStreamException; import org.apache.tools.bzip2.CBZip2InputStream; +import org.apache.tools.bzip2.CBZip2OutputStream; import org.xml.sax.SAXException; import com.osmand.data.City; @@ -114,7 +116,7 @@ public class DataExtraction implements IMapLocationListener { stream = new FileInputStream(DefaultLauncherConstants.pathToOsmFile); } else { stream = new FileInputStream(DefaultLauncherConstants.pathToOsmBz2File); - if (stream.read() != 66 || stream.read() != 90) + if (stream.read() != 'B' || stream.read() != 'Z') throw new RuntimeException( "The source stream must start with the characters BZ if it is to be read as a BZip2 stream."); else @@ -157,6 +159,10 @@ public class DataExtraction implements IMapLocationListener { // TODO temp solution n.putTag(OSMTagKey.AMENITY.getValue(), OSMTagKey.LEISURE.getValue()); amenities.add(n); + } else if (n.getTag(OSMTagKey.TOURISM) != null) { + // TODO temp solution + n.putTag(OSMTagKey.AMENITY.getValue(), OSMTagKey.TOURISM.getValue()); + amenities.add(n); } if (n.getTag(OSMTagKey.PLACE) != null) { places.add(n); @@ -220,8 +226,10 @@ public class DataExtraction implements IMapLocationListener { } } + DataTileManager amenitiesManager = new DataTileManager(); for(Node node : amenities){ country.registerAmenity(node); + amenitiesManager.registerObject(node.getLatitude(), node.getLongitude(), node.getLatLon()); } @@ -234,18 +242,24 @@ public class DataExtraction implements IMapLocationListener { } } } - mapPanel.setPoints(waysManager); + mapPanel.setPoints(amenitiesManager); runUI(country); List interestedObjects = new ArrayList(); - MapUtils.addIdsToList(places, interestedObjects); +// MapUtils.addIdsToList(places, interestedObjects); MapUtils.addIdsToList(amenities, interestedObjects); - MapUtils.addIdsToList(mapWays, interestedObjects); +// MapUtils.addIdsToList(mapWays, interestedObjects); // MapUtils.addIdsToList(buildings, interestedObjects); if (DefaultLauncherConstants.writeTestOsmFile != null) { OSMStorageWriter writer = new OSMStorageWriter(storage.getRegisteredEntities()); - writer.saveStorage(new FileOutputStream(DefaultLauncherConstants.writeTestOsmFile), interestedObjects, true); + OutputStream output = new FileOutputStream(DefaultLauncherConstants.writeTestOsmFile); + output.write('B'); + output.write('Z'); + output = new CBZip2OutputStream(output); + + writer.saveStorage(output, interestedObjects, true); + output.close(); } System.out.println(); diff --git a/DataExtractionOSM/src/com/osmand/MapPanel.java b/DataExtractionOSM/src/com/osmand/MapPanel.java index ef0712f58c..bb2a0bad0b 100644 --- a/DataExtractionOSM/src/com/osmand/MapPanel.java +++ b/DataExtractionOSM/src/com/osmand/MapPanel.java @@ -4,6 +4,7 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Graphics; +import java.awt.Image; import java.awt.Point; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; @@ -11,18 +12,28 @@ 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; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.UIManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import com.osmand.DataExtraction.ExitListener; import com.osmand.data.DataTileManager; import com.osmand.osm.LatLon; @@ -31,6 +42,8 @@ import com.osmand.osm.MapUtils; public class MapPanel extends JPanel { private static final long serialVersionUID = 1L; + + private static final Log log = LogFactory.getLog(MapPanel.class); public static void main(String[] args) throws IOException { @@ -59,7 +72,7 @@ public class MapPanel extends JPanel { // tile size of map private final int tileSize = 256; - + // file name with tiles private final File fileWithTiles; @@ -78,18 +91,20 @@ public class MapPanel extends JPanel { private List listeners = new ArrayList(); - - // cached data to draw image - private BufferedImage[][] images; + private Image[][] images; private int xStartingImage = 0; private int yStartingImage = 0; - private List pointsToDraw = new ArrayList(); + private List pointsToDraw = new ArrayList(); + + private AsyncLoadTileThread autoThread = new AsyncLoadTileThread(); + Map cache = new HashMap(); public MapPanel(File fileWithTiles) { this.fileWithTiles = fileWithTiles; + autoThread.start(); initUI(); } @@ -105,6 +120,7 @@ public class MapPanel extends JPanel { @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++) { @@ -123,8 +139,6 @@ public class MapPanel extends JPanel { } } - - } else { g.drawImage(images[i][j], i * tileSize+xStartingImage, j * tileSize + yStartingImage, this); } @@ -137,6 +151,9 @@ public class MapPanel extends JPanel { 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); + g.drawString(s, 5, 20); g.fillOval(getWidth()/2 - 2, getHeight()/2 -2, 4, 4); @@ -144,13 +161,13 @@ public class MapPanel extends JPanel { g.drawOval(getWidth()/2 - 5, getHeight()/2 -5, 10, 10); } - public String getFile(int x, int y){ + public String getFile(int zoom, int x, int y){ return map +"/"+zoom+"/"+(x) +"/"+y+".png"; } - Map cache = new HashMap(); - public BufferedImage getImageFor(int x, int y) throws IOException{ - String file = getFile(x, y); + + public Image getImageFor(int x, int y) throws IOException{ + String file = getFile(zoom, x, y); if(!cache.containsKey(file)){ // ZipEntry en = fileWithTiles.getEntry(file); File en = new File(fileWithTiles, file); @@ -167,13 +184,104 @@ public class MapPanel extends JPanel { cache.put(file, ImageIO.read(en)); System.out.println("Loaded " + (System.currentTimeMillis() - time)); } else { - cache.put(file, null); + autoThread.requestTileToLoad(zoom, x, y); } } 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 tilesToLoad = new Stack(); + 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 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(){ @@ -187,41 +295,38 @@ public class MapPanel extends JPanel { } } - double xTileLeft = getXTile() -getSize().width/(2d*tileSize); - double xTileRight = getXTile() + getSize().width/(2d*tileSize); - double yTileUp = getYTile() -getSize().height/(2d*tileSize); - double yTileDown = getYTile() + getSize().height/(2d*tileSize); + double xTileLeft = getXTile() - getSize().width / (2d * tileSize); + double xTileRight = getXTile() + getSize().width / (2d * tileSize); + double yTileUp = getYTile() - getSize().height / (2d * tileSize); + double yTileDown = getYTile() + getSize().height / (2d * tileSize); - xStartingImage = - (int) ((xTileLeft - Math.floor(xTileLeft))*tileSize); - yStartingImage = - (int) ((yTileUp - Math.floor(yTileUp))*tileSize); - - int tileXCount = ((int)xTileRight - (int) xTileLeft + 1); - int tileYCount = ((int)yTileDown - (int) yTileUp + 1); + xStartingImage = -(int) ((xTileLeft - Math.floor(xTileLeft)) * tileSize); + yStartingImage = -(int) ((yTileUp - Math.floor(yTileUp)) * tileSize); + + autoThread.cancelAllPreviousTile(); + int tileXCount = ((int) xTileRight - (int) xTileLeft + 1); + int tileYCount = ((int) yTileDown - (int) yTileUp + 1); images = new BufferedImage[tileXCount][tileYCount]; - for(int i=0; i objects = points.getObjects(latUp, longUp, latDown, longDown); pointsToDraw.clear(); - for(LatLon n : objects){ - int pixX = MapUtils.getPixelShiftX(zoom, n.getLongitude(), this.longitude, tileSize) + - getWidth() / 2; - int pixY = MapUtils.getPixelShiftY(zoom, n.getLatitude(), this.latitude, tileSize) + - getHeight() / 2; - if(pixX >= 0 && pixY >= 0){ + for (LatLon n : objects) { + int pixX = MapUtils.getPixelShiftX(zoom, n.getLongitude(), this.longitude, tileSize) + getWidth() / 2; + int pixY = MapUtils.getPixelShiftY(zoom, n.getLatitude(), this.latitude, tileSize) + getHeight() / 2; + if (pixX >= 0 && pixY >= 0) { pointsToDraw.add(new Point(pixX, pixY)); } } - - } repaint(); @@ -317,11 +422,15 @@ public class MapPanel extends JPanel { } if(e.getID() == KeyEvent.KEY_TYPED){ if(e.getKeyChar() == '+'){ - zoom ++; - processed = true; + if(zoom < 18){ + zoom ++; + processed = true; + } } else if(e.getKeyChar() == '-'){ - zoom --; - processed = true; + if(zoom > 1){ + zoom --; + processed = true; + } } } diff --git a/DataExtractionOSM/src/com/osmand/data/Region.java b/DataExtractionOSM/src/com/osmand/data/Region.java index 9cf8c3635a..13b72376fa 100644 --- a/DataExtractionOSM/src/com/osmand/data/Region.java +++ b/DataExtractionOSM/src/com/osmand/data/Region.java @@ -94,6 +94,7 @@ public class Region { public void registerAmenity(Node n){ amenities.registerObject(n.getLatitude(), n.getLongitude(), n); } + public City registerCity(Node c){ City city = new City(c); diff --git a/DataExtractionOSM/src/com/osmand/osm/OSMSettings.java b/DataExtractionOSM/src/com/osmand/osm/OSMSettings.java index f668233508..8a46a3ea8a 100644 --- a/DataExtractionOSM/src/com/osmand/osm/OSMSettings.java +++ b/DataExtractionOSM/src/com/osmand/osm/OSMSettings.java @@ -16,7 +16,8 @@ public class OSMSettings { // POI AMENITY("amenity"), SHOP("shop"), - LEISURE("leisure"), + LEISURE("leisure"), + TOURISM("tourism"), ; private final String value; diff --git a/OsmAnd/AndroidManifest.xml b/OsmAnd/AndroidManifest.xml index 07db37c191..2f2500f075 100644 --- a/OsmAnd/AndroidManifest.xml +++ b/OsmAnd/AndroidManifest.xml @@ -5,7 +5,7 @@ android:versionName="1.0"> + android:label="@string/app_name" android:launchMode="singleTop"> @@ -19,4 +19,5 @@ + \ No newline at end of file diff --git a/OsmAnd/src/com/osmand/MapActivity.java b/OsmAnd/src/com/osmand/MapActivity.java index f64d8b1b22..e717c89993 100644 --- a/OsmAnd/src/com/osmand/MapActivity.java +++ b/OsmAnd/src/com/osmand/MapActivity.java @@ -9,6 +9,7 @@ import android.location.LocationManager; import android.os.Bundle; import android.os.Environment; import android.view.View; +import android.view.Window; import android.view.View.OnClickListener; import android.widget.ImageButton; import android.widget.ZoomControls; @@ -31,9 +32,13 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - setContentView(R.layout.main); + requestWindowFeature(Window.FEATURE_NO_TITLE); +// getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, +// WindowManager.LayoutParams.FLAG_FULLSCREEN); + + + setContentView(R.layout.main); mapView = (OsmandMapTileView) findViewById(R.id.View01); mapView.setFileWithTiles(new File(Environment.getExternalStorageDirectory(), "osmand/tiles/Mapnik")); mapView.addMapLocationListener(this); @@ -72,8 +77,6 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE); service.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this); - service.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, this); - } @@ -98,6 +101,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat @Override public void onStatusChanged(String provider, int status, Bundle extras) { + // TODO when provider disabled reset lastKnownLocation! } public void validatePointOfView(){