diff --git a/.gitignore b/.gitignore index 6bc1ff9c7e..30f7f4ac5f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ routing*.xml rendering_types.xml countries.reginfo +regions.ocbf h_*.png g_*.png mm_*.png diff --git a/OsmAnd-java/build.xml b/OsmAnd-java/build.xml index 1f82e72ac5..0ff589a494 100644 --- a/OsmAnd-java/build.xml +++ b/OsmAnd-java/build.xml @@ -46,6 +46,7 @@ + @@ -92,6 +93,17 @@ + + + + + + + + + + + diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryInspector.java b/OsmAnd-java/src/net/osmand/binary/BinaryInspector.java index 19a1bd825d..2ea570f158 100644 --- a/OsmAnd-java/src/net/osmand/binary/BinaryInspector.java +++ b/OsmAnd-java/src/net/osmand/binary/BinaryInspector.java @@ -52,7 +52,7 @@ public class BinaryInspector { in.inspector(args); // test cases show info -// in.inspector(new String[]{"-vmap", "-vmapobjects", "-zoom=7", "-osm=/home/victor/projects/osmand/temp/zoom_7.osm", "/home/victor/projects/osmand/osm-gen/World_basemap_2.obf"}); + in.inspector(new String[]{"/home/victor/projects/osmand/osm-gen/World_basemap_2z.obf"}); // in.inspector(new String[]{"-vmap", "-vmapobjects", /*"-vstreets", "-bbox=14.4,50.1,14.5,50.01", */"/home/victor/projects/osmand/osm-gen/Osmand_regions.obf"}); // test case extract parts // test case @@ -67,16 +67,16 @@ public class BinaryInspector { } private void println(String s) { - if(vInfo != null && vInfo.osm) { + if(vInfo != null && vInfo.osm && vInfo.osmOut == null) { // ignore } else { System.out.println(s); } } - + private void print(String s) { - if(vInfo != null && vInfo.osm) { + if(vInfo != null && vInfo.osm && vInfo.osmOut == null) { // ignore } else { System.out.print(s); @@ -696,6 +696,7 @@ public class BinaryInspector { } String name = names.get(keys[j]); name = name.replace("'", "'"); + name = name.replace("&", "&"); tags.append("\t\n"); } } diff --git a/OsmAnd-java/src/net/osmand/map/OsmandRegions.java b/OsmAnd-java/src/net/osmand/map/OsmandRegions.java index 28583cde8d..bf1b47defa 100644 --- a/OsmAnd-java/src/net/osmand/map/OsmandRegions.java +++ b/OsmAnd-java/src/net/osmand/map/OsmandRegions.java @@ -15,28 +15,44 @@ import java.util.*; public class OsmandRegions { + private BinaryMapIndexReader reader; Map> countries = new HashMap>(); - QuadTree quadTree = new QuadTree(new QuadRect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE), - 8, 0.55f); + QuadTree quadTree = null ; + + Integer downloadNameType = null; Integer prefixType = null; - Integer suffixType = null; - static String FILE_NAME = "/home/victor/projects/osmand/osm-gen/Osmand_regions.obf"; + private Integer suffixType; + private String fname; - public OsmandRegions() { + + public void prepareFile(String fileName) throws IOException { + reader = new BinaryMapIndexReader(new RandomAccessFile(fileName, "r")); } - - Integer getDownloadNameType(){ - return downloadNameType; + public String getDownloadName(BinaryMapDataObject o) { + if(downloadNameType == null) { + return null; + } + return o.getNameByType(downloadNameType); } - Integer getPrefixType() { - return prefixType; + public String getPrefix(BinaryMapDataObject o) { + if(prefixType == null) { + return null; + } + return o.getNameByType(prefixType); } - Integer getSuffixType() { - return suffixType; + public String getSuffix(BinaryMapDataObject o) { + if(suffixType == null) { + return null; + } + return o.getNameByType(suffixType); + } + + public boolean isInitialized(){ + return reader != null; } @@ -55,7 +71,7 @@ public class OsmandRegions { return t % 2 == 1; } - public List getCountries(int tile31x, int tile31y) { + private List getCountries(int tile31x, int tile31y) { HashSet set = new HashSet(quadTree.queryInBox(new QuadRect(tile31x, tile31y, tile31x, tile31y), new ArrayList())); List result = new ArrayList(); @@ -80,9 +96,15 @@ public class OsmandRegions { } - public List queryNoInit(String fileName, final int tile31x, final int tile31y) throws IOException { + public List query(final int tile31x, final int tile31y) throws IOException { + if(quadTree != null) { + return getCountries(tile31x, tile31y); + } + return queryNoInit(tile31x, tile31y); + } + + private List queryNoInit(final int tile31x, final int tile31y) throws IOException { final List result = new ArrayList(); - BinaryMapIndexReader reader = new BinaryMapIndexReader(new RandomAccessFile(fileName, "r")); BinaryMapIndexReader.SearchRequest sr = BinaryMapIndexReader.buildSearchRequest(tile31x, tile31x, tile31y, tile31y, 5, new BinaryMapIndexReader.SearchFilter() { @Override @@ -97,6 +119,7 @@ public class OsmandRegions { if (object.getPointsLength() < 1) { return false; } + initTypes(object); if (contain(object, tile31x, tile31y)) { result.add(object); } @@ -114,10 +137,40 @@ public class OsmandRegions { } + public List queryBbox(int lx, int rx, int ty, int by) throws IOException { + final List result = new ArrayList(); + BinaryMapIndexReader.SearchRequest sr = BinaryMapIndexReader.buildSearchRequest(lx, rx, ty, by, + 5, new BinaryMapIndexReader.SearchFilter() { + @Override + public boolean accept(TIntArrayList types, BinaryMapIndexReader.MapIndex index) { + return true; + } + }, new ResultMatcher() { - private void init(String fileName) throws IOException { + @Override + public boolean publish(BinaryMapDataObject object) { + if (object.getPointsLength() < 1) { + return false; + } + initTypes(object); + result.add(object); + return false; + } - BinaryMapIndexReader reader = new BinaryMapIndexReader(new RandomAccessFile(fileName, "r")); + @Override + public boolean isCancelled() { + return false; + } + } + ); + reader.searchMapIndex(sr); + return result; + } + + + public void cacheAllCountries() throws IOException { + quadTree = new QuadTree(new QuadRect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE), + 8, 0.55f); BinaryMapIndexReader.SearchRequest sr = BinaryMapIndexReader.buildSearchRequest(0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, 5, new BinaryMapIndexReader.SearchFilter() { @Override @@ -132,14 +185,7 @@ public class OsmandRegions { if (object.getPointsLength() < 1) { return false; } - if (downloadNameType == null) { - downloadNameType = object.getMapIndex().getRule("download_name", null); - prefixType = object.getMapIndex().getRule("region_prefix", null); - suffixType = object.getMapIndex().getRule("region_suffix", null); - if (downloadNameType == null) { - throw new IllegalStateException(); - } - } + initTypes(object); String nm = object.getNameByType(downloadNameType); if (!countries.containsKey(nm)) { LinkedList ls = new LinkedList(); @@ -180,45 +226,50 @@ public class OsmandRegions { reader.searchMapIndex(sr); } + private void initTypes(BinaryMapDataObject object) { + if (downloadNameType == null) { + downloadNameType = object.getMapIndex().getRule("download_name", null); + prefixType = object.getMapIndex().getRule("region_prefix", null); + suffixType = object.getMapIndex().getRule("region_suffix", null); + if (downloadNameType == null) { + throw new IllegalStateException(); + } + } + } + private static void testCountry(OsmandRegions or, double lat, double lon, String... test) throws IOException { - //List cs = or.getCountries(MapUtils.get31TileNumberX(lon), MapUtils.get31TileNumberY(lat)); - List cs = or.queryNoInit(FILE_NAME, MapUtils.get31TileNumberX(lon), MapUtils.get31TileNumberY(lat)); - if(cs.size() != test.length) { - StringBuilder found = new StringBuilder(); + long t = System.currentTimeMillis(); + List cs = or.query(MapUtils.get31TileNumberX(lon), MapUtils.get31TileNumberY(lat)); + Set expected = new TreeSet(Arrays.asList(test)); + Set found = new TreeSet(); for(BinaryMapDataObject b : cs) { - found.append(b.getName()).append(' '); + found.add(b.getName()); } - throw new IllegalStateException(" Expected " + Arrays.toString(test) + " - Lat " + lat + " lon " + lon + ", but found : " + found); - } - for (int i = 0; i < test.length; i++) { - String nm = cs.get(i).getName(); - if (!test[i].equals(nm)) { - throw new IllegalStateException(" Expected " + test[i] + " but was " + nm); - } + if(!found.equals(expected)) { + throw new IllegalStateException(" Expected " + expected + " but was " + found); } + System.out.println("Found " + expected + " in " + (System.currentTimeMillis() - t) + " ms"); } public static void main(String[] args) throws IOException { OsmandRegions or = new OsmandRegions(); - long t = System.currentTimeMillis(); -// or.init(FILE_NAME); - System.out.println(System.currentTimeMillis() - t); + or.prepareFile("/home/victor/projects/osmand/osm-gen/Osmand_regions.obf"); + +// long t = System.currentTimeMillis(); +// or.cacheAllCountries(); +// System.out.println("Init " + (System.currentTimeMillis() - t)); //testCountry(or, 15.8, 23.09, "chad"); testCountry(or, 52.10, 4.92, "netherlands"); testCountry(or, 52.15, 7.50, "nordrhein-westfalen"); testCountry(or, 40.0760, 9.2807, "italy"); - System.out.println(System.currentTimeMillis() - t); testCountry(or, 28.8056, 29.9858, "africa", "egypt" ); - System.out.println(System.currentTimeMillis() - t); testCountry(or, 35.7521, 139.7887, "japan"); - System.out.println(System.currentTimeMillis() - t); testCountry(or, 46.5145, 102.2580, "mongolia"); - System.out.println(System.currentTimeMillis() - t); } } diff --git a/OsmAnd/build.xml b/OsmAnd/build.xml index 647e58406c..d33079da22 100644 --- a/OsmAnd/build.xml +++ b/OsmAnd/build.xml @@ -47,6 +47,7 @@ + diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 9edb20a847..082f86a6e7 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -9,6 +9,7 @@ 3. All your modified/created strings are in the top of the file (to make easier find what\'s translated). PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy --> + base world map Map Styles OsmAnd supports displaying the offline vector maps in different map styles to suit your to needs: \n\nOther than the balanced \'default\' map style, you may in \'Menu\' → \'Configure screen\' → \'Map Style\' select for example diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java index 478d9957ad..43f761d306 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java @@ -37,20 +37,7 @@ import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin; import net.osmand.plus.render.MapVectorLayer; import net.osmand.plus.render.RenderingIcons; import net.osmand.plus.routing.RoutingHelper; -import net.osmand.plus.views.ContextMenuLayer; -import net.osmand.plus.views.FavoritesLayer; -import net.osmand.plus.views.GPXLayer; -import net.osmand.plus.views.MapControlsLayer; -import net.osmand.plus.views.MapInfoLayer; -import net.osmand.plus.views.MapTileLayer; -import net.osmand.plus.views.OsmandMapTileView; -import net.osmand.plus.views.POIMapLayer; -import net.osmand.plus.views.PointLocationLayer; -import net.osmand.plus.views.PointNavigationLayer; -import net.osmand.plus.views.RouteInfoLayer; -import net.osmand.plus.views.RouteLayer; -import net.osmand.plus.views.TransportInfoLayer; -import net.osmand.plus.views.TransportStopsLayer; +import net.osmand.plus.views.*; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.ProgressDialog; @@ -94,6 +81,7 @@ public class MapActivityLayers { private ContextMenuLayer contextMenuLayer; private RouteInfoLayer routeInfoLayer; private MapControlsLayer mapControlsLayer; + private DownloadedRegionsLayer downloadedRegionsLayer; public MapActivityLayers(MapActivity activity) { this.activity = activity; @@ -117,7 +105,10 @@ public class MapActivityLayers { // 0.5 layer mapVectorLayer = new MapVectorLayer(mapTileLayer); mapView.addLayer(mapVectorLayer, 0.5f); - + + downloadedRegionsLayer = new DownloadedRegionsLayer(); + mapView.addLayer(downloadedRegionsLayer, 0.5f); + // 0.9 gpx layer gpxLayer = new GPXLayer(); mapView.addLayer(gpxLayer, 0.9f); diff --git a/OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java b/OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java index ffef43d5c4..4c6be837c9 100644 --- a/OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java +++ b/OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java @@ -22,6 +22,7 @@ import java.util.Set; import net.osmand.IProgress; import net.osmand.NativeLibrary.NativeSearchResult; import net.osmand.PlatformUtil; +import net.osmand.ResultMatcher; import net.osmand.access.AccessibleToast; import net.osmand.binary.BinaryMapDataObject; import net.osmand.binary.BinaryMapIndexReader; @@ -249,7 +250,7 @@ public class MapRenderRepositories { } NativeSearchResult resultHandler = library.searchObjectsForRendering(leftX, rightX, topY, bottomY, zoom, renderingReq, - checkForDuplicateObjectIds, this, context.getString(R.string.switch_to_raster_map_to_see)); + checkForDuplicateObjectIds, this, /*context.getString(R.string.switch_to_raster_map_to_see)*/ ""); if (checkWhetherInterrupted()) { resultHandler.deleteNativeResult(); return false; @@ -399,12 +400,6 @@ public class MapRenderRepositories { mapIndex.initMapEncodingRule(0, 1, "natural", "coastline"); mapIndex.initMapEncodingRule(0, 2, "name", ""); } - // avoid overflow int errors - BinaryMapDataObject o = new BinaryMapDataObject(new int[] { leftX + (rightX - leftX) / 2, topY + (bottomY - topY) / 2 }, - new int[] { mapIndex.coastlineEncodingType }, null, -1); - o.setMapIndex(mapIndex); - o.putObjectName(mapIndex.nameEncodingType, context.getString(R.string.switch_to_raster_map_to_see)); - tempResult.add(o); } if(zoom <= BASEMAP_ZOOM || emptyData) { tempResult.addAll(basemapResult); @@ -443,6 +438,36 @@ public class MapRenderRepositories { } } + + public boolean checkIfMapIsEmpty(int leftX, int rightX, int topY, int bottomY, int zoom){ + final boolean[] empty = new boolean[] {true}; + SearchRequest searchRequest = BinaryMapIndexReader.buildSearchRequest(leftX, rightX, topY, bottomY, zoom, + null, new ResultMatcher() { + @Override + public boolean publish(BinaryMapDataObject object) { + empty[0] = false; + return false; + } + + @Override + public boolean isCancelled() { + return !empty[0]; + } + }); + for (BinaryMapIndexReader c : files.values()) { + if(!c.isBasemap()) { + try { + c.searchMapIndex(searchRequest); + } catch (IOException e) { + } + if(!empty[0]) { + return false; + } + } + } + return empty[0]; + } + public synchronized void loadMap(RotatedTileBox tileRect, List notifyList) { interrupted = false; if (currentRenderingContext != null) { diff --git a/OsmAnd/src/net/osmand/plus/render/NativeOsmandLibrary.java b/OsmAnd/src/net/osmand/plus/render/NativeOsmandLibrary.java index ab7ad31577..b422e94675 100644 --- a/OsmAnd/src/net/osmand/plus/render/NativeOsmandLibrary.java +++ b/OsmAnd/src/net/osmand/plus/render/NativeOsmandLibrary.java @@ -50,7 +50,7 @@ public class NativeOsmandLibrary extends NativeLibrary { log.debug("Creating NativeOsmandLibrary instance..."); //$NON-NLS-1$ library = new NativeOsmandLibrary(true); isNativeSupported = true; - } catch(Throwable e) { + } catch(Error e) { log.error("Failed to load new native library", e); //$NON-NLS-1$ } if(!isNativeSupported) { diff --git a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java index e0a182aa08..75b438ae4f 100644 --- a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java +++ b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java @@ -18,6 +18,7 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; +import android.os.AsyncTask; import net.osmand.AndroidUtils; import net.osmand.GeoidAltitudeCorrection; import net.osmand.IProgress; @@ -67,6 +68,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.DisplayMetrics; import android.view.WindowManager; +import net.osmand.map.OsmandRegions; /** * Resource manager is responsible to work with all resources @@ -123,6 +125,8 @@ public class ResourceManager { protected final Map routingMapFiles = Collections.synchronizedMap(new LinkedHashMap()); protected final MapRenderRepositories renderer; + + protected final OsmandRegions regions; protected final MapTileDownloader tileDownloader; @@ -134,7 +138,7 @@ public class ResourceManager { this.context = context; this.renderer = new MapRenderRepositories(context); asyncLoadingThread.start(); - + tileDownloader = MapTileDownloader.getInstance(Version.getFullVersion(context)); resetStoreDirectory(); @@ -145,7 +149,8 @@ public class ResourceManager { // at least 3*9? float tiles = (dm.widthPixels / 256 + 2) * (dm.heightPixels / 256 + 2) * 3; log.info("Tiles to load in memory : " + tiles); - maxImgCacheSize = (int) (tiles) ; + maxImgCacheSize = (int) (tiles) ; + regions = new OsmandRegions(); } public MapTileDownloader getMapTileDownloader() { @@ -405,6 +410,7 @@ public class ResourceManager { warnings.addAll(checkAssets(progress)); initRenderers(progress); geoidAltitudeCorrection = new GeoidAltitudeCorrection(context.getAppPath(null)); + indexRegionsBoundaries(progress, false); // do it lazy // indexingImageTiles(progress); warnings.addAll(indexingMaps(progress)); @@ -413,7 +419,23 @@ public class ResourceManager { return warnings; } - + + private void indexRegionsBoundaries(IProgress progress, boolean overwrite) { + try { + File file = context.getAppPath("regions.ocbf"); + if (file != null) { + if (!file.exists() || overwrite) { + Algorithms.streamCopy(OsmandRegions.class.getResourceAsStream("regions.ocbf"), + new FileOutputStream(file)); + } + } + regions.prepareFile(file.getAbsolutePath()); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + + public List indexVoiceFiles(IProgress progress){ File file = context.getAppPath(IndexConstants.VOICE_INDEX_DIR); file.mkdirs(); @@ -445,7 +467,8 @@ public class ResourceManager { applicationDataDir.mkdirs(); if(applicationDataDir.canWrite()){ try { - progress.startTask(context.getString(R.string.installing_new_resources), -1); + progress.startTask(context.getString(R.string.installing_new_resources), -1); + indexRegionsBoundaries(progress, true); AssetManager assetManager = context.getAssets(); boolean isFirstInstall = context.getSettings().PREVIOUS_INSTALLED_VERSION.get().equals(""); unpackBundledAssets(assetManager, applicationDataDir, progress, isFirstInstall); @@ -938,6 +961,10 @@ public class ResourceManager { public GeoidAltitudeCorrection getGeoidAltitudeCorrection() { return geoidAltitudeCorrection; } + + public OsmandRegions getOsmandRegions() { + return regions; + } protected synchronized void clearTiles() { diff --git a/OsmAnd/src/net/osmand/plus/views/DownloadedRegionsLayer.java b/OsmAnd/src/net/osmand/plus/views/DownloadedRegionsLayer.java new file mode 100644 index 0000000000..e151062fd5 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/DownloadedRegionsLayer.java @@ -0,0 +1,265 @@ +package net.osmand.plus.views; + +import android.content.Context; +import android.content.Intent; +import android.graphics.*; +import android.graphics.Paint.Cap; +import android.graphics.Paint.Join; +import android.graphics.Paint.Style; +import android.os.AsyncTask; +import android.text.TextPaint; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.FrameLayout; +import net.osmand.IndexConstants; +import net.osmand.binary.BinaryMapDataObject; +import net.osmand.map.OsmandRegions; +import net.osmand.plus.GPXUtilities.GPXFile; +import net.osmand.plus.GPXUtilities.WptPt; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.R; +import net.osmand.plus.activities.DownloadIndexActivity; +import net.osmand.plus.activities.OsmandIntents; +import net.osmand.plus.resources.ResourceManager; +import net.osmand.render.RenderingRuleSearchRequest; +import net.osmand.render.RenderingRulesStorage; +import net.osmand.util.Algorithms; +import net.osmand.util.MapUtils; + +import java.io.IOException; +import java.util.*; + +public class DownloadedRegionsLayer extends OsmandMapLayer { + + private OsmandMapTileView view; + + private Paint paint; + + private Path path; + + private OsmandSettings settings; + + private OsmandRegions osmandRegions; + + + + private List objectsToDraw = new ArrayList(); + private RectF queriedBBox = new RectF(); + private int queriedZoom = 0; + private boolean basemapExists = true; + private boolean noMapsPresent = false; + private TextPaint textPaint; + private AsyncTask currentTask = null; + private AsyncTask pendingTask = null; + private ResourceManager rm; + private Button downloadBtn; + private StringBuilder filter = new StringBuilder(); + + @Override + public void initLayer(final OsmandMapTileView view) { + this.view = view; + settings = view.getSettings(); + rm = view.getApplication().getResourceManager(); + osmandRegions = rm.getOsmandRegions(); + + paint = new Paint(); + paint.setStyle(Style.FILL_AND_STROKE); + paint.setStrokeWidth(1); + paint.setColor(Color.argb(100, 50, 200, 50)); + paint.setAntiAlias(true); + paint.setStrokeCap(Cap.ROUND); + paint.setStrokeJoin(Join.ROUND); + + textPaint = new TextPaint(); + final WindowManager wmgr = (WindowManager) view.getApplication().getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics dm = new DisplayMetrics(); + wmgr.getDefaultDisplay().getMetrics(dm); + textPaint.setStrokeWidth(21 * dm.scaledDensity); + textPaint.setAntiAlias(true); + textPaint.setTextAlign(Paint.Align.CENTER); + + FrameLayout fl = (FrameLayout) view.getParent(); + downloadBtn = new Button(view.getContext()); + downloadBtn.setVisibility(View.GONE); + downloadBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + final Intent intent = new Intent(view.getContext(), OsmandIntents.getDownloadIndexActivity()); + intent.putExtra(DownloadIndexActivity.FILTER_KEY, filter.toString()); + view.getContext().startActivity(intent); + } + }); + + + final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + lp.gravity = Gravity.CENTER; + fl.addView(downloadBtn, lp); + + + path = new Path(); + + } + + + private static int ZOOM_TO_SHOW_BORDERS_ST = 5; + private static int ZOOM_TO_SHOW_BORDERS = 7; + private static int ZOOM_TO_SHOW_MAP_NAMES = 12; + + @Override + public void onDraw(Canvas canvas, RectF latLonBox, RectF tilesRect, DrawSettings nightMode) { + final int zoom = view.getZoom(); + if(downloadBtn.getVisibility() == View.VISIBLE) { + downloadBtn.setVisibility(View.GONE); + } + if (zoom >= ZOOM_TO_SHOW_BORDERS_ST && (zoom < ZOOM_TO_SHOW_BORDERS || zoom >= ZOOM_TO_SHOW_MAP_NAMES) && + osmandRegions.isInitialized()) { + if (!queriedBBox.contains(latLonBox) || Math.abs(queriedZoom - zoom) > 2) { + float w = Math.abs(latLonBox.width() / 2); + float h = Math.abs(latLonBox.height() / 2); + final RectF rf = new RectF(latLonBox.left - w, latLonBox.top + h, latLonBox.right + w, latLonBox.bottom - h); + AsyncTask> task = new AsyncTask>() { + @Override + protected List doInBackground(Object... params) { + if (queriedBBox.contains(rf)) { + return null; + } + if(zoom < ZOOM_TO_SHOW_MAP_NAMES) { + basemapExists = rm.getRenderer().basemapExists(); + } + List result = null; + int left = MapUtils.get31TileNumberX(rf.left); + int right = MapUtils.get31TileNumberX(rf.right); + int top = MapUtils.get31TileNumberY(rf.top); + int bottom = MapUtils.get31TileNumberY(rf.bottom); + final boolean empty = rm.getRenderer().checkIfMapIsEmpty(left, right, top, bottom, zoom); + noMapsPresent = empty; + if(!empty && zoom >= ZOOM_TO_SHOW_MAP_NAMES) { + return Collections.emptyList(); + } + try { + result = osmandRegions.queryBbox(left, right, top, bottom); + } catch (IOException e) { + return result; + } + Iterator it = result.iterator(); + while (it.hasNext()) { + BinaryMapDataObject o = it.next(); + if (zoom < ZOOM_TO_SHOW_BORDERS) { + // + } else { + if (!osmandRegions.contain(o, left / 2 + right / 2, top / 2 + bottom / 2)) { + it.remove(); + } + } + } + return result; + } + + @Override + protected void onPreExecute() { + currentTask = this; + } + + @Override + protected void onPostExecute(List result) { + if (result != null) { + queriedBBox = rf; + objectsToDraw = result; + queriedZoom = zoom; + } + currentTask = null; + if (pendingTask != null) { + pendingTask.execute(); + pendingTask = null; + } + } + }; + if (currentTask == null) { + task.execute(); + } else { + pendingTask = task; + } + } + final List currentObjects = objectsToDraw; + if ((currentObjects != null && currentObjects.size() > 0) || noMapsPresent) { + if (zoom >= ZOOM_TO_SHOW_MAP_NAMES) { + StringBuilder s = new StringBuilder(view.getResources().getString(R.string.download_files)); + filter.setLength(0); + if ((currentObjects != null && currentObjects.size() > 0)) { + for (int i = 0; i < currentObjects.size(); i++) { + if (i > 0) { + s.append(" & "); + } else { + s.append(" "); + } + final BinaryMapDataObject o = currentObjects.get(i); + String string = Algorithms.capitalizeFirstLetterAndLowercase(o.getName()); + filter.append(string + " "); + if (osmandRegions.getPrefix(o) != null) { + string = Algorithms.capitalizeFirstLetterAndLowercase(osmandRegions.getPrefix(o)) + " " + string; + } + s.append(string); + } + } + downloadBtn.setVisibility(View.VISIBLE); + downloadBtn.setText(s.toString()); + } else { + if(!basemapExists) { + filter.setLength(0); + filter.append("basemap"); + downloadBtn.setVisibility(View.VISIBLE); + downloadBtn.setText(view.getResources().getString(R.string.download_files) + " " + + view.getResources().getString(R.string.base_world_map)); + } + for (BinaryMapDataObject o : currentObjects) { + final String key = Algorithms.capitalizeFirstLetterAndLowercase(osmandRegions.getDownloadName(o)) + + IndexConstants.BINARY_MAP_INDEX_EXT; + if (!rm.getIndexFileNames().containsKey(key)) { + continue; + } + path.reset(); + double lat = MapUtils.get31LatitudeY(o.getPoint31YTile(0)); + double lon = MapUtils.get31LongitudeX(o.getPoint31XTile(0)); + path.moveTo(view.getRotatedMapXForPoint(lat, lon), view.getRotatedMapYForPoint(lat, lon)); + for(int j = 1 ; j < o.getPointsLength(); j++) { + lat = MapUtils.get31LatitudeY(o.getPoint31YTile(j)); + lon = MapUtils.get31LongitudeX(o.getPoint31XTile(j)); + path.lineTo(view.getRotatedMapXForPoint(lat, lon), + view.getRotatedMapYForPoint(lat, lon)); + } + canvas.drawPath(path, paint); + } + } + + } + } + } + + + @Override + public void destroyLayer() { + ((FrameLayout)downloadBtn.getParent()).removeView(downloadBtn); + } + + @Override + public boolean drawInScreenPixels() { + return false; + } + + @Override + public boolean onLongPressEvent(PointF point) { + return false; + } + + @Override + public boolean onSingleTap(PointF point) { + return false; + } + + +} diff --git a/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java b/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java index f716822829..0e065938f2 100644 --- a/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java +++ b/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java @@ -413,7 +413,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall public int getCenterPointY() { if (mapPosition == OsmandSettings.BOTTOM_CONSTANT) { - return 3 * getHeight() / 4; + return 4 * getHeight() / 5; } return getHeight() / 2; }