Proccess incompleted tiles

This commit is contained in:
Victor Shcherb 2012-04-07 00:57:13 +02:00
parent 453747920e
commit 5eb925c0cb
12 changed files with 260 additions and 160 deletions

View file

@ -13,7 +13,7 @@ public class ToDoConstants {
// Map QuadTree (skip small areas!!!) // Map QuadTree (skip small areas!!!)
// Routing index !! // Routing index !!
// Identify coastline areas and pure ocean areas !!! // Identify coastline areas and pure ocean areas !!! Show high zoom level for coatline if coastline is broken
// TODO Delete/Extract the code with multipolygons ! (coastline)) // TODO Delete/Extract the code with multipolygons ! (coastline))
// Render : different texts support render.xml // Render : different texts support render.xml

View file

@ -46,13 +46,7 @@ public class BinaryInspector {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
inspector(args); inspector(args);
// test cases show info // test cases show info
// inspector(new String[]{"/home/victor/projects/OsmAnd/temp/Belarus_europe.obf"}); inspector(new String[]{"/home/victor/projects/OsmAnd/data/osm-gen/basemap_coastlines"});
// inspector(new String[]{"-v","C:\\Users\\tpd\\osmand\\Housenumbers.obf"});
//inspector(new String[]{"/home/victor/projects/OsmAnd/data/osm-gen/saved/Belarus-newzooms-new-rt.obf"});
// inspector(new String[]{"/home/victor/projects/OsmAnd/download/spain/Spain_europe_1_small.obf"});
inspector(new String[]{"-vpoi", "/home/victor/projects/OsmAnd/data/osm-gen/10m_coastline_out.obf"
/*"/home/victor/projects/OsmAnd/data/osm-gen/Luxembourg.obf"*/});
// test case extract parts // test case extract parts
@ -519,7 +513,7 @@ public class BinaryInspector {
continue; continue;
// throw new NullPointerException("Type " + obj.getAdditionalTypes()[j] + "was not found"); // throw new NullPointerException("Type " + obj.getAdditionalTypes()[j] + "was not found");
} }
b.append(pair.toSimpleString()+"("+types[j]+")"); b.append(pair.toSimpleString()+" ("+types[j]+")");
} }
b.append("]"); b.append("]");
if(obj.getAdditionalTypes() != null && obj.getAdditionalTypes().length > 0){ if(obj.getAdditionalTypes() != null && obj.getAdditionalTypes().length > 0){

View file

@ -57,6 +57,13 @@ public class BinaryMapDataObject {
return objectNames; return objectNames;
} }
public void putObjectName(int type, String name){
if(objectNames == null){
objectNames = new TIntObjectHashMap<String>();
}
objectNames.put(type, name);
}
public int[][] getPolygonInnerCoordinates() { public int[][] getPolygonInnerCoordinates() {
return polygonInnerCoordinates; return polygonInnerCoordinates;
} }

View file

@ -60,6 +60,7 @@ public class BinaryMapIndexReader {
private int version; private int version;
private long dateCreated; private long dateCreated;
// keep them immutable inside // keep them immutable inside
private boolean basemap = false;
private List<MapIndex> mapIndexes = new ArrayList<MapIndex>(); private List<MapIndex> mapIndexes = new ArrayList<MapIndex>();
private List<PoiRegion> poiIndexes = new ArrayList<PoiRegion>(); private List<PoiRegion> poiIndexes = new ArrayList<PoiRegion>();
private List<AddressRegion> addressIndexes = new ArrayList<AddressRegion>(); private List<AddressRegion> addressIndexes = new ArrayList<AddressRegion>();
@ -72,6 +73,8 @@ public class BinaryMapIndexReader {
private final BinaryMapPoiReaderAdapter poiAdapter; private final BinaryMapPoiReaderAdapter poiAdapter;
private final BinaryMapAddressReaderAdapter addressAdapter; private final BinaryMapAddressReaderAdapter addressAdapter;
private static String BASEMAP_NAME = "basemap";
public BinaryMapIndexReader(final RandomAccessFile raf) throws IOException { public BinaryMapIndexReader(final RandomAccessFile raf) throws IOException {
this(raf, false); this(raf, false);
@ -90,6 +93,7 @@ public class BinaryMapIndexReader {
addressIndexes = new ArrayList<AddressRegion>(referenceToSameFile.addressIndexes); addressIndexes = new ArrayList<AddressRegion>(referenceToSameFile.addressIndexes);
transportIndexes = new ArrayList<TransportIndex>(referenceToSameFile.transportIndexes); transportIndexes = new ArrayList<TransportIndex>(referenceToSameFile.transportIndexes);
indexes = new ArrayList<BinaryIndexPart>(referenceToSameFile.indexes); indexes = new ArrayList<BinaryIndexPart>(referenceToSameFile.indexes);
basemap = referenceToSameFile.basemap;
} }
public BinaryMapIndexReader(final RandomAccessFile raf, boolean readOnlyMapData) throws IOException { public BinaryMapIndexReader(final RandomAccessFile raf, boolean readOnlyMapData) throws IOException {
@ -136,6 +140,7 @@ public class BinaryMapIndexReader {
mapIndex.filePointer = codedIS.getTotalBytesRead(); mapIndex.filePointer = codedIS.getTotalBytesRead();
int oldLimit = codedIS.pushLimit(mapIndex.length); int oldLimit = codedIS.pushLimit(mapIndex.length);
readMapIndex(mapIndex); readMapIndex(mapIndex);
basemap = basemap || mapIndex.isBaseMap();
codedIS.popLimit(oldLimit); codedIS.popLimit(oldLimit);
codedIS.seek(mapIndex.filePointer + mapIndex.length); codedIS.seek(mapIndex.filePointer + mapIndex.length);
mapIndexes.add(mapIndex); mapIndexes.add(mapIndex);
@ -215,6 +220,14 @@ public class BinaryMapIndexReader {
return indexes; return indexes;
} }
public List<MapIndex> getMapIndexes() {
return mapIndexes;
}
public boolean isBasemap() {
return basemap;
}
public boolean containsMapData(){ public boolean containsMapData(){
return mapIndexes.size() > 0; return mapIndexes.size() > 0;
} }
@ -668,6 +681,13 @@ public class BinaryMapIndexReader {
case MapDataBox.TOP_FIELD_NUMBER : case MapDataBox.TOP_FIELD_NUMBER :
tree.top = codedIS.readSInt32() + atop; tree.top = codedIS.readSInt32() + atop;
break; break;
case MapDataBox.OCEAN_FIELD_NUMBER :
if(codedIS.readBool()) {
tree.ocean = Boolean.TRUE;
} else {
tree.ocean = Boolean.FALSE;
}
break;
case MapDataBox.SHIFTTOMAPDATA_FIELD_NUMBER : case MapDataBox.SHIFTTOMAPDATA_FIELD_NUMBER :
tree.mapDataBlock = readInt() + tree.filePointer; tree.mapDataBlock = readInt() + tree.filePointer;
break; break;
@ -852,7 +872,12 @@ public class BinaryMapIndexReader {
foundSubtrees.add(current); foundSubtrees.add(current);
break; break;
case MapDataBox.OCEAN_FIELD_NUMBER : case MapDataBox.OCEAN_FIELD_NUMBER :
current.ocean = codedIS.readBool(); if(codedIS.readBool()) {
current.ocean = Boolean.TRUE;
} else {
current.ocean = Boolean.FALSE;
}
req.publishOceanTile(current.ocean);
break; break;
case MapDataBox.BOXES_FIELD_NUMBER : case MapDataBox.BOXES_FIELD_NUMBER :
// left, ... already initialized // left, ... already initialized
@ -860,8 +885,8 @@ public class BinaryMapIndexReader {
child.length = readInt(); child.length = readInt();
child.filePointer = codedIS.getTotalBytesRead(); child.filePointer = codedIS.getTotalBytesRead();
int oldLimit = codedIS.pushLimit(child.length); int oldLimit = codedIS.pushLimit(child.length);
if(current.ocean){ if(current.ocean != null ){
child.ocean = true; child.ocean = current.ocean;
} }
searchMapTreeBounds(child, current, req, foundSubtrees); searchMapTreeBounds(child, current, req, foundSubtrees);
codedIS.popLimit(oldLimit); codedIS.popLimit(oldLimit);
@ -1228,6 +1253,9 @@ public class BinaryMapIndexReader {
public static class SearchRequest<T> { public static class SearchRequest<T> {
private List<T> searchResults = new ArrayList<T>(); private List<T> searchResults = new ArrayList<T>();
private boolean land = false;
private boolean ocean = false;
private ResultMatcher<T> resultMatcher; private ResultMatcher<T> resultMatcher;
// 31 zoom tiles // 31 zoom tiles
@ -1276,6 +1304,14 @@ public class BinaryMapIndexReader {
return false; return false;
} }
protected void publishOceanTile(boolean ocean){
if(ocean) {
this.ocean = true;
} else {
this.land = true;
}
}
public List<T> getSearchResults() { public List<T> getSearchResults() {
return searchResults; return searchResults;
} }
@ -1294,11 +1330,21 @@ public class BinaryMapIndexReader {
return false; return false;
} }
public boolean isOcean() {
return ocean;
}
public boolean isLand() {
return land;
}
public void clearSearchResults(){ public void clearSearchResults(){
// recreate whole list to allow GC collect old data // recreate whole list to allow GC collect old data
searchResults = new ArrayList<T>(); searchResults = new ArrayList<T>();
cacheCoordinates.clear(); cacheCoordinates.clear();
cacheTypes.clear(); cacheTypes.clear();
land = false;
ocean = false;
numberOfVisitedObjects = 0; numberOfVisitedObjects = 0;
numberOfAcceptedObjects = 0; numberOfAcceptedObjects = 0;
numberOfReadSubtrees = 0; numberOfReadSubtrees = 0;
@ -1331,8 +1377,13 @@ public class BinaryMapIndexReader {
} }
public void finishInitializingTags() { public void finishInitializingTags() {
coastlineBrokenEncodingType = decodingRules.size() * 2 + 1; int free = decodingRules.size() * 2 + 1;
coastlineBrokenEncodingType = free++;
initMapEncodingRule(0, coastlineBrokenEncodingType, "natural", "coastline_broken"); initMapEncodingRule(0, coastlineBrokenEncodingType, "natural", "coastline_broken");
if(landEncodingType == -1){
landEncodingType = free++;
initMapEncodingRule(0, landEncodingType, "natural", "land");
}
} }
private void initMapEncodingRule(int type, int id, String tag, String val) { private void initMapEncodingRule(int type, int id, String tag, String val) {
@ -1367,6 +1418,9 @@ public class BinaryMapIndexReader {
} }
} }
public boolean isBaseMap(){
return name != null && name.toLowerCase().contains(BASEMAP_NAME);
}
} }
public static class TagValuePair { public static class TagValuePair {
@ -1455,7 +1509,7 @@ public class BinaryMapIndexReader {
int length = 0; int length = 0;
long mapDataBlock = 0; long mapDataBlock = 0;
boolean ocean = false; Boolean ocean = null;
int left = 0; int left = 0;
int right = 0; int right = 0;
@ -1482,6 +1536,12 @@ public class BinaryMapIndexReader {
return filePointer; return filePointer;
} }
@Override
public String toString(){
return "Top Lat " + ((float) MapUtils.get31LatitudeY(top)) + " lon " + ((float) MapUtils.get31LongitudeX(left))
+ " Bottom lat " + ((float) MapUtils.get31LatitudeY(bottom)) + " lon " + ((float) MapUtils.get31LongitudeX(right));
}
} }

View file

@ -196,7 +196,6 @@ public class BinaryMapIndexWriter {
codedOutStream.writeInt32(OsmandOdb.OsmAndMapIndex.MapRootLevel.RIGHT_FIELD_NUMBER, rightX); codedOutStream.writeInt32(OsmandOdb.OsmAndMapIndex.MapRootLevel.RIGHT_FIELD_NUMBER, rightX);
codedOutStream.writeInt32(OsmandOdb.OsmAndMapIndex.MapRootLevel.TOP_FIELD_NUMBER, topY); codedOutStream.writeInt32(OsmandOdb.OsmAndMapIndex.MapRootLevel.TOP_FIELD_NUMBER, topY);
codedOutStream.writeInt32(OsmandOdb.OsmAndMapIndex.MapRootLevel.BOTTOM_FIELD_NUMBER, bottomY); codedOutStream.writeInt32(OsmandOdb.OsmAndMapIndex.MapRootLevel.BOTTOM_FIELD_NUMBER, bottomY);
stackBounds.push(new Bounds(leftX, rightX, topY, bottomY)); stackBounds.push(new Bounds(leftX, rightX, topY, bottomY));
} }

View file

@ -9,7 +9,6 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet; import java.util.BitSet;
import java.util.Iterator; import java.util.Iterator;
@ -17,14 +16,12 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamException;
import net.osmand.Algoritms; import net.osmand.Algoritms;
import net.osmand.binary.OsmandOdb.MapData; import net.osmand.binary.OsmandOdb.MapData;
import net.osmand.binary.OsmandOdb.MapDataBlock; import net.osmand.binary.OsmandOdb.MapDataBlock;
import net.osmand.binary.OsmandOdb.MapDataBlock.Builder;
import net.osmand.data.MapAlgorithms; import net.osmand.data.MapAlgorithms;
import net.osmand.data.preparation.MapZooms.MapZoomPair; import net.osmand.data.preparation.MapZooms.MapZoomPair;
import net.osmand.osm.Entity; import net.osmand.osm.Entity;
@ -54,20 +51,21 @@ public class CoastlineProcessor {
public static final byte TILE_ZOOMLEVEL = 12; public static final byte TILE_ZOOMLEVEL = 12;
private static final byte BITMASK = 0x3; private static final byte BITMASK = 0x3;
private static final int BITS_COUNT = (1 << TILE_ZOOMLEVEL) * (1 << TILE_ZOOMLEVEL); private static final int BITS_COUNT = (1 << TILE_ZOOMLEVEL) * (1 << TILE_ZOOMLEVEL);
private BitSet seaTileInfo = new BitSet(BITS_COUNT);
private BitSet landTileInfo = new BitSet(BITS_COUNT);
private final int zoomWaySmothness; private final int zoomWaySmothness;
private final MapRenderingTypes renderingTypes; private final MapRenderingTypes renderingTypes;
private final MapZooms mapZooms; private final MapZooms mapZooms;
private final Log logMapDataWarn; private final Log logMapDataWarn;
private SimplisticQuadTree quadTree; private SimplisticQuadTree[] quadTrees;
private static class SimplisticQuadTree { private static class SimplisticQuadTree {
public boolean ocean;
public boolean land;
int zoom; int zoom;
int x; int x;
int y; int y;
boolean ocean;
boolean land;
public SimplisticQuadTree(int x, int y, int zoom) { public SimplisticQuadTree(int x, int y, int zoom) {
this.x = x; this.x = x;
@ -76,7 +74,8 @@ public class CoastlineProcessor {
} }
SimplisticQuadTree[] children = null; SimplisticQuadTree[] children = null;
List<Way> coastlines = null; Map<MapZoomPair,List<Way>> coastlines = null;
public SimplisticQuadTree[] getAllChildren(){ public SimplisticQuadTree[] getAllChildren(){
initChildren(); initChildren();
@ -87,11 +86,23 @@ public class CoastlineProcessor {
return children != null; return children != null;
} }
public void addCoastline(Way w){ public void addCoastline(MapZoomPair p, Way w){
if(coastlines == null) { if(coastlines == null) {
coastlines = new ArrayList<Way>(); coastlines = new LinkedHashMap<MapZooms.MapZoomPair, List<Way>>();
} }
coastlines.add(w); if(!coastlines.containsKey(p)){
coastlines.put(p, new ArrayList<Way>());
}
coastlines.get(p).add(w);
}
public boolean coastlinesDefined(MapZoomPair p){
return coastlines != null && coastlines.get(p) != null;
}
public List<Way> getCoastlines(MapZoomPair p) {
return coastlines.get(p);
} }
public SimplisticQuadTree getOrCreateSubTree(int x, int y, int zm) { public SimplisticQuadTree getOrCreateSubTree(int x, int y, int zm) {
@ -127,10 +138,15 @@ public class CoastlineProcessor {
this.mapZooms = mapZooms; this.mapZooms = mapZooms;
this.renderingTypes = renderingTypes; this.renderingTypes = renderingTypes;
this.zoomWaySmothness = zoomWaySmothness; this.zoomWaySmothness = zoomWaySmothness;
quadTree = constructTilesQuadTree(); constructBitSetInfo();
quadTrees = new SimplisticQuadTree[mapZooms.getLevels().size()];
for (int i=0;i< mapZooms.getLevels().size(); i++) {
MapZoomPair p = mapZooms.getLevels().get(i);
quadTrees[i] = constructTilesQuadTree(Math.min(p.getMaxZoom() - 1, 1));
}
} }
private void constructBitSetInfo(BitSet seaTileInfo , BitSet landTileInfo) { private void constructBitSetInfo() {
try { try {
InputStream stream = CoastlineProcessor.class.getResourceAsStream("oceantiles_12.dat.bz2"); InputStream stream = CoastlineProcessor.class.getResourceAsStream("oceantiles_12.dat.bz2");
@ -167,7 +183,7 @@ public class CoastlineProcessor {
} }
} }
private boolean isWaterTile(BitSet seaTileInfo, int x, int y, int zoom) { private boolean isWaterTile(int x, int y, int zoom) {
if (zoom >= TILE_ZOOMLEVEL) { if (zoom >= TILE_ZOOMLEVEL) {
int x1 = x >> (zoom - TILE_ZOOMLEVEL); int x1 = x >> (zoom - TILE_ZOOMLEVEL);
int y1 = y >> (zoom - TILE_ZOOMLEVEL); int y1 = y >> (zoom - TILE_ZOOMLEVEL);
@ -190,7 +206,7 @@ public class CoastlineProcessor {
} }
} }
private boolean isLandTile(BitSet landTileInfo, int x, int y, int zoom) { private boolean isLandTile(int x, int y, int zoom) {
if (zoom >= TILE_ZOOMLEVEL) { if (zoom >= TILE_ZOOMLEVEL) {
int x1 = x >> (zoom - TILE_ZOOMLEVEL); int x1 = x >> (zoom - TILE_ZOOMLEVEL);
int y1 = y >> (zoom - TILE_ZOOMLEVEL); int y1 = y >> (zoom - TILE_ZOOMLEVEL);
@ -213,83 +229,75 @@ public class CoastlineProcessor {
} }
} }
public SimplisticQuadTree constructTilesQuadTree(){ public SimplisticQuadTree constructTilesQuadTree(int maxZoom){
SimplisticQuadTree rootTree = new SimplisticQuadTree(0, 0, 0); SimplisticQuadTree rootTree = new SimplisticQuadTree(0, 0, 0);
BitSet seaTileInfo = new BitSet(BITS_COUNT);
BitSet landTileInfo = new BitSet(BITS_COUNT);
constructBitSetInfo(seaTileInfo, landTileInfo);
int baseZoom = 4; int baseZoom = 4;
int tiles = 1 << baseZoom; int tiles = 1 << baseZoom;
ArrayList<SimplisticQuadTree> toVisit = new ArrayList<SimplisticQuadTree>(); ArrayList<SimplisticQuadTree> toVisit = new ArrayList<SimplisticQuadTree>();
int cnt = 0;
for (int x = 0; x < tiles; x++) { for (int x = 0; x < tiles; x++) {
for (int y = 0; y < tiles; y++) { for (int y = 0; y < tiles; y++) {
toVisit.add(rootTree.getOrCreateSubTree(x, y, baseZoom)); toVisit.add(rootTree.getOrCreateSubTree(x, y, baseZoom));
} }
} }
int ntc = 0; initializeQuadTree(rootTree, baseZoom, maxZoom, toVisit);
for (int zoom = baseZoom; zoom <= TILE_ZOOMLEVEL && !toVisit.isEmpty(); zoom++) { return rootTree;
cnt = 0;
}
protected ArrayList<SimplisticQuadTree> initializeQuadTree(SimplisticQuadTree rootTree, int baseZoom, int maxZoom,
ArrayList<SimplisticQuadTree> toVisit) {
for (int zoom = baseZoom; zoom <= maxZoom && !toVisit.isEmpty(); zoom++) {
ArrayList<SimplisticQuadTree> newToVisit = new ArrayList<SimplisticQuadTree>(); ArrayList<SimplisticQuadTree> newToVisit = new ArrayList<SimplisticQuadTree>();
for (SimplisticQuadTree subtree : toVisit) { for (SimplisticQuadTree subtree : toVisit) {
int x = subtree.x; int x = subtree.x;
int y = subtree.y; int y = subtree.y;
if (isWaterTile(seaTileInfo, x, y, zoom)) { if (isWaterTile(x, y, zoom)) {
cnt++;
rootTree.getOrCreateSubTree(x, y, zoom).ocean = true; rootTree.getOrCreateSubTree(x, y, zoom).ocean = true;
} else if (isLandTile(landTileInfo, x, y, zoom)) { } else if (isLandTile(x, y, zoom)) {
rootTree.getOrCreateSubTree(x, y, zoom).land = true; rootTree.getOrCreateSubTree(x, y, zoom).land = true;
cnt++;
} else if(zoom < TILE_ZOOMLEVEL){ } else if(zoom < TILE_ZOOMLEVEL){
SimplisticQuadTree[] vis = rootTree.getOrCreateSubTree(x, y, zoom).getOrCreateSubTree(x, y, zoom) SimplisticQuadTree[] vis = rootTree.getOrCreateSubTree(x, y, zoom).getOrCreateSubTree(x, y, zoom)
.getAllChildren(); .getAllChildren();
for (SimplisticQuadTree t : vis) { for (SimplisticQuadTree t : vis) {
newToVisit.add(t); newToVisit.add(t);
} }
} else {
ntc ++;
} }
} }
// System.out.println(" Zoom " + zoom + " count " + cnt);
toVisit = newToVisit; toVisit = newToVisit;
} }
// System.out.println("Not covered " + ntc + " from " + (float) ntc / ((1 << TILE_ZOOMLEVEL) * (1<<TILE_ZOOMLEVEL))); return toVisit;
return rootTree;
} }
public void writeCoastlinesFile(BinaryMapIndexWriter writer) throws IOException { public void writeCoastlinesFile(BinaryMapIndexWriter writer, String regionName) throws IOException {
writeCoastlinesFile(writer, quadTree); writer.startWriteMapIndex(regionName);
}
private void writeCoastlinesFile(BinaryMapIndexWriter writer, SimplisticQuadTree simplisticQuadTree) throws IOException {
writer.startWriteMapIndex("Coastline");
// write map encoding rules // write map encoding rules
writer.writeMapEncodingRules(renderingTypes.getEncodingRuleTypes()); writer.writeMapEncodingRules(renderingTypes.getEncodingRuleTypes());
// TODO zooms file iterate in cycle int i = 0;
MapZoomPair p = mapZooms.getLevels().get(mapZooms.getLevels().size() - 1); for (MapZoomPair p : mapZooms.getLevels()) {
// write map levels and map index // write map levels and map index
writer.startWriteMapLevelIndex(p.getMinZoom(), p.getMinZoom(), 0, 0, (1 << 31) - 1, (1 << 31) - 1); writer.startWriteMapLevelIndex(p.getMinZoom(), p.getMaxZoom(), 0, (1 << 31) - 1, 0, (1 << 31) - 1);
Map<SimplisticQuadTree, BinaryFileReference> refs = new LinkedHashMap<CoastlineProcessor.SimplisticQuadTree, BinaryFileReference>(); Map<SimplisticQuadTree, BinaryFileReference> refs = new LinkedHashMap<CoastlineProcessor.SimplisticQuadTree, BinaryFileReference>();
writeBinaryMapTree(simplisticQuadTree, writer, refs); writeBinaryMapTree(quadTrees[i], writer, refs, p);
// without data blocks // without data blocks
writeBinaryMapBlock(simplisticQuadTree, writer, refs); writeBinaryMapBlock(quadTrees[i], writer, refs, p);
writer.endWriteMapLevelIndex();
writer.endWriteMapLevelIndex();
i++;
}
writer.endWriteMapIndex(); writer.endWriteMapIndex();
writer.flush(); writer.flush();
} }
private void writeBinaryMapBlock(SimplisticQuadTree simplisticQuadTree, BinaryMapIndexWriter writer, private void writeBinaryMapBlock(SimplisticQuadTree simplisticQuadTree, BinaryMapIndexWriter writer,
Map<SimplisticQuadTree, BinaryFileReference> refs) throws IOException { Map<SimplisticQuadTree, BinaryFileReference> refs, MapZoomPair p) throws IOException {
Iterator<Entry<SimplisticQuadTree, BinaryFileReference>> it = refs.entrySet().iterator(); Iterator<Entry<SimplisticQuadTree, BinaryFileReference>> it = refs.entrySet().iterator();
TIntArrayList type = new TIntArrayList(); TIntArrayList type = new TIntArrayList();
type.add(renderingTypes.getCoastlineRuleType().getTargetId()); type.add(renderingTypes.getCoastlineRuleType().getTargetId());
@ -299,10 +307,12 @@ public class CoastlineProcessor {
MapDataBlock.Builder dataBlock = MapDataBlock.newBuilder(); MapDataBlock.Builder dataBlock = MapDataBlock.newBuilder();
SimplisticQuadTree quad = e.getKey(); SimplisticQuadTree quad = e.getKey();
for (Way w : quad.coastlines) { for (Way w : quad.getCoastlines(p)) {
dataBlock.setBaseId(w.getId()); dataBlock.setBaseId(w.getId());
List<Node> res = new ArrayList<Node>();
MapAlgorithms.simplifyDouglasPeucker(w.getNodes(), p.getMaxZoom() - 2 + 8 + zoomWaySmothness, 3, res);
ByteArrayOutputStream bcoordinates = new ByteArrayOutputStream(); ByteArrayOutputStream bcoordinates = new ByteArrayOutputStream();
for (Node n : w.getNodes()) { for (Node n : res) {
if (n != null) { if (n != null) {
int y = MapUtils.get31TileNumberY(n.getLatitude()); int y = MapUtils.get31TileNumberY(n.getLatitude());
int x = MapUtils.get31TileNumberX(n.getLongitude()); int x = MapUtils.get31TileNumberX(n.getLongitude());
@ -323,13 +333,19 @@ public class CoastlineProcessor {
} }
private void writeBinaryMapTree(SimplisticQuadTree quadTree, BinaryMapIndexWriter writer, private void writeBinaryMapTree(SimplisticQuadTree quadTree, BinaryMapIndexWriter writer,
Map<SimplisticQuadTree, BinaryFileReference> refs) throws IOException { Map<SimplisticQuadTree, BinaryFileReference> refs, MapZoomPair p) throws IOException {
int xL = (quadTree.x) << (31 - quadTree.zoom); int xL = (quadTree.x) << (31 - quadTree.zoom);
int xR = (quadTree.x + 1) << (31 - quadTree.zoom) - 1; int xR = ((quadTree.x + 1) << (31 - quadTree.zoom)) - 1;
int yT = (quadTree.y) << (31 - quadTree.zoom); int yT = (quadTree.y) << (31 - quadTree.zoom);
int yB = (quadTree.y + 1) << (31 - quadTree.zoom) - 1; int yB = ((quadTree.y + 1) << (31 - quadTree.zoom)) - 1;
BinaryFileReference ref = writer.startMapTreeElement(xL, xR, yT, yB, false, boolean defined = quadTree.coastlinesDefined(p);
quadTree.ocean, quadTree.land); boolean ocean = false;
boolean land = false;
if (!defined) {
ocean = quadTree.ocean || isWaterTile(quadTree.x, quadTree.y, quadTree.zoom);
land = quadTree.land || isLandTile(quadTree.x, quadTree.y, quadTree.zoom);
}
BinaryFileReference ref = writer.startMapTreeElement(xL, xR, yT, yB, defined, ocean, land);
if (ref != null) { if (ref != null) {
refs.put(quadTree, ref); refs.put(quadTree, ref);
} }
@ -338,7 +354,7 @@ public class CoastlineProcessor {
SimplisticQuadTree[] allChildren = quadTree.getAllChildren(); SimplisticQuadTree[] allChildren = quadTree.getAllChildren();
for (SimplisticQuadTree ch : allChildren) { for (SimplisticQuadTree ch : allChildren) {
writeBinaryMapTree(ch, writer, refs); writeBinaryMapTree(ch, writer, refs, p);
} }
} }
writer.endWriteMapTreeElement(); writer.endWriteMapTreeElement();
@ -346,11 +362,11 @@ public class CoastlineProcessor {
} }
public void processCoastline(Way e) { public void processCoastline(Way e) {
// for(MapZoomPair p : mapZooms.getLevels()) {
renderingTypes.getCoastlineRuleType().updateFreq(); renderingTypes.getCoastlineRuleType().updateFreq();
MapZoomPair p = mapZooms.getLevels().get(mapZooms.getLevels().size() - 1); int ij = 0;
{ for(MapZoomPair p : mapZooms.getLevels()) {
int z = (p.getMinZoom() + p.getMaxZoom()) / 2; SimplisticQuadTree quadTree = quadTrees[ij++];
int z = Math.min((p.getMinZoom() + p.getMaxZoom()) / 2, p.getMinZoom() + 3);
List<Node> ns = e.getNodes(); List<Node> ns = e.getNodes();
if(ns.size() < 2) { if(ns.size() < 2) {
return; return;
@ -382,18 +398,27 @@ public class CoastlineProcessor {
// increase boundaries to drop into another tile // increase boundaries to drop into another tile
int leftX = (tilex << (31 - z)) - 1; int leftX = (tilex << (31 - z)) - 1;
int rightX = (tilex + 1) << (31 - z); int rightX = (tilex + 1) << (31 - z);
if( rightX < 0 ){ if (rightX < 0) {
rightX = Integer.MAX_VALUE; rightX = Integer.MAX_VALUE;
} }
int topY = (tiley << (31 - z)) - 1; int topY = (tiley << (31 - z)) - 1;
int bottomY = (tiley + 1) << (31 - z); int bottomY = (tiley + 1) << (31 - z);
if( bottomY < 0 ){ if (bottomY < 0) {
bottomY = Integer.MAX_VALUE; bottomY = Integer.MAX_VALUE;
} }
long inter = MapAlgorithms.calculateIntersection(px31, py31, nx31, ny31, leftX, rightX, bottomY, topY); long inter = MapAlgorithms.calculateIntersection(px31, py31, nx31, ny31, leftX, rightX, bottomY, topY);
int cy31 = (int) inter; int cy31 = (int) inter;
int cx31 = (int) (inter >> 32l); int cx31 = (int) (inter >> 32l);
if (inter == -1) {
cx31 = nx31;
cy31 = ny31;
i++;
logMapDataWarn.warn("Can't find intersection for " + MapUtils.get31LongitudeX(px31) + ","
+ MapUtils.get31LatitudeY(py31) + " - " + +MapUtils.get31LongitudeX(nx31) + ","
+ MapUtils.get31LatitudeY(ny31));
}
prevNode = new Node(MapUtils.get31LatitudeY(cy31), MapUtils.get31LongitudeX(cx31), -1000); prevNode = new Node(MapUtils.get31LatitudeY(cy31), MapUtils.get31LongitudeX(cx31), -1000);
px31 = cx31; px31 = cx31;
py31 = cy31; py31 = cy31;
@ -409,16 +434,16 @@ public class CoastlineProcessor {
System.err.println("Tile " + tilex + " / " + tiley + " at " + z + " can not be found"); System.err.println("Tile " + tilex + " / " + tiley + " at " + z + " can not be found");
} }
} }
quad.addCoastline(w); quad.addCoastline(p, w);
}
}
} }
} }
///////////////////////////// OLD CODE /////////////////////////////// ///////////////////////////// NOT USED CODE TO DELETE ///////////////////////////////
public void processCoastlineOld(Way e) { public void processCoastlineOld(Way e) {
WayChain chain = null; WayChain chain = null;

View file

@ -641,7 +641,10 @@ public class IndexCreator {
// creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/osm-maps/luxembourg.osm.pbf"), // creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/osm-maps/luxembourg.osm.pbf"),
// creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/osm-maps/cuba2.osm.bz2"), // creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/osm-maps/cuba2.osm.bz2"),
// new ConsoleProgressImplementation(1), null, zooms, rt, log); // new ConsoleProgressImplementation(1), null, zooms, rt, log);
zooms = MapZooms.parseZooms("1-5;6-14"); // ;6-8;9-14
zooms = MapZooms.parseZooms("1-3;4-6;7-9;10-14");
creator.setRegionName("basemap");
creator.setMapFileName("basemap_coastlines.obf");
creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/basemap/10m_coastline_out.osm"), creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/basemap/10m_coastline_out.osm"),
new ConsoleProgressImplementation(1), null, zooms, rt, log); new ConsoleProgressImplementation(1), null, zooms, rt, log);

View file

@ -98,7 +98,6 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
} }
public void indexMapRelationsAndMultiPolygons(Entity e, OsmDbAccessorContext ctx) throws SQLException { public void indexMapRelationsAndMultiPolygons(Entity e, OsmDbAccessorContext ctx) throws SQLException {
// indexHighwayRestrictions(e, ctx);
indexMultiPolygon(e, ctx); indexMultiPolygon(e, ctx);
} }
@ -558,7 +557,7 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
closePreparedStatements(mapBinaryStat, mapLowLevelBinaryStat); closePreparedStatements(mapBinaryStat, mapLowLevelBinaryStat);
mapConnection.commit(); mapConnection.commit();
if(COASTLINE_PROCESS) { if(COASTLINE_PROCESS) {
coastlineProcessor.writeCoastlinesFile(writer); coastlineProcessor.writeCoastlinesFile(writer, regionName);
return; return;
} }
try { try {

View file

@ -355,6 +355,8 @@
<filter minzoom="14" textSize="14" ref="false"/> <filter minzoom="14" textSize="14" ref="false"/>
</filter> </filter>
<filter minzoom="3" textSize="14" textColor="#9d6c9d" textWrapWidth="35" tag="natural" value="coastline"/>
<filter minzoom="3" textSize="14" textColor="#9d6c9d" textWrapWidth="35" tag="natural" value="land"/>
<!-- Location names --> <!-- Location names -->
<filter minzoom="3" textSize="14" textColor="#9d6c9d" textWrapWidth="20" tag="place" value="country"/> <filter minzoom="3" textSize="14" textColor="#9d6c9d" textWrapWidth="20" tag="place" value="country"/>
<filter minzoom="4" textSize="14" textColor="#9d6c9d" textWrapWidth="20" tag="place" value="state"/> <filter minzoom="4" textSize="14" textColor="#9d6c9d" textWrapWidth="20" tag="place" value="state"/>

View file

@ -180,7 +180,7 @@
\n\t\'To compass\' - Map will continuously be aligned with device compass reading \n\t\'To compass\' - Map will continuously be aligned with device compass reading
\n\tHint: To quickly change between rotation by compass and the one you selected in settings, you can simply tap on the compass needle in map view.</string> \n\tHint: To quickly change between rotation by compass and the one you selected in settings, you can simply tap on the compass needle in map view.</string>
<string name="switch_to_raster_map_to_see">No offline vector map present for this location.\n\t\n\tYou can download one in \'Settings\' -> \'Offline data\', or switch to online maps via \'Settings\' -> \'Map configuration\'.</string> <string name="switch_to_raster_map_to_see">No offline vector map present for this location. You can download one in Settings (Offline data), or switch to online maps.</string>
<string name="binary_map_download_success">Download successful.\n\t\n\tTo use activate \'Settings\' -> \'Map configuration\' -> \'Offline vector maps\'.</string> <string name="binary_map_download_success">Download successful.\n\t\n\tTo use activate \'Settings\' -> \'Map configuration\' -> \'Offline vector maps\'.</string>
<string name="tip_day_night_mode">Day/Night Mode</string> <string name="tip_day_night_mode">Day/Night Mode</string>

View file

@ -59,12 +59,12 @@ public class MapRenderRepositories {
private final static Log log = LogUtil.getLog(MapRenderRepositories.class); private final static Log log = LogUtil.getLog(MapRenderRepositories.class);
private final Context context; private final Context context;
private final static int BASEMAP_ZOOM = 7;
private Handler handler; private Handler handler;
private Map<String, BinaryMapIndexReader> files = new LinkedHashMap<String, BinaryMapIndexReader>(); private Map<String, BinaryMapIndexReader> files = new LinkedHashMap<String, BinaryMapIndexReader>();
private Set<String> nativeFiles = new HashSet<String>(); private Set<String> nativeFiles = new HashSet<String>();
private OsmandRenderer renderer; private OsmandRenderer renderer;
private static String BASEMAP_NAME = "basemap";
// lat/lon box of requested vector data // lat/lon box of requested vector data
private RectF cObjectsBox = new RectF(); private RectF cObjectsBox = new RectF();
@ -229,8 +229,8 @@ public class MapRenderRepositories {
} }
public boolean basemapExists() { public boolean basemapExists() {
for (String f : files.keySet()) { for (BinaryMapIndexReader f : files.values()) {
if (f.toLowerCase().contains(BASEMAP_NAME)) { if (f.isBasemap()) {
return true; return true;
} }
} }
@ -245,21 +245,9 @@ public class MapRenderRepositories {
int bottomY = MapUtils.get31TileNumberY(dataBox.bottom); int bottomY = MapUtils.get31TileNumberY(dataBox.bottom);
int topY = MapUtils.get31TileNumberY(dataBox.top); int topY = MapUtils.get31TileNumberY(dataBox.top);
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
// search lower level zooms only in basemap for now :) before it was intersection of maps on zooms 5-7 // TODO coastline/land tiles
boolean basemapSearch = false;
if (zoom <= 7) {
for (String f : files.keySet()) {
if (f.toLowerCase().contains(BASEMAP_NAME)) {
basemapSearch = true;
break;
}
}
}
NativeSearchResult resultHandler = null; NativeSearchResult resultHandler = null;
for (String mapName : files.keySet()) { for (String mapName : files.keySet()) {
if (basemapSearch && !mapName.toLowerCase().contains(BASEMAP_NAME)) {
continue;
}
BinaryMapIndexReader reader = files.get(mapName); BinaryMapIndexReader reader = files.get(mapName);
if(!reader.containsMapData(leftX, topY, rightX, bottomY, zoom)) { if(!reader.containsMapData(leftX, topY, rightX, bottomY, zoom)) {
continue; continue;
@ -301,10 +289,12 @@ public class MapRenderRepositories {
} }
try { try {
int count = 0; int count = 0;
ArrayList<BinaryMapDataObject> tempList = new ArrayList<BinaryMapDataObject>(); ArrayList<BinaryMapDataObject> tempResult = new ArrayList<BinaryMapDataObject>();
ArrayList<BinaryMapDataObject> basemapResult = new ArrayList<BinaryMapDataObject>();
System.gc(); // to clear previous objects System.gc(); // to clear previous objects
TLongSet ids = new TLongHashSet(); TLongSet ids = new TLongHashSet();
List<BinaryMapDataObject> coastLines = new ArrayList<BinaryMapDataObject>(); List<BinaryMapDataObject> coastLines = new ArrayList<BinaryMapDataObject>();
List<BinaryMapDataObject> basemapCoastLines = new ArrayList<BinaryMapDataObject>();
int leftX = MapUtils.get31TileNumberX(cLeftLongitude); int leftX = MapUtils.get31TileNumberX(cLeftLongitude);
int rightX = MapUtils.get31TileNumberX(cRightLongitude); int rightX = MapUtils.get31TileNumberX(cRightLongitude);
int bottomY = MapUtils.get31TileNumberY(cBottomLatitude); int bottomY = MapUtils.get31TileNumberY(cBottomLatitude);
@ -340,56 +330,81 @@ public class MapRenderRepositories {
if (zoom > 16) { if (zoom > 16) {
searchFilter = null; searchFilter = null;
} }
// search lower level zooms only in basemap for now :) before it was intersection of maps on zooms 5-7 boolean ocean = false;
boolean basemapSearch = false; MapIndex mi = null;
if (zoom <= 7) { searchRequest = BinaryMapIndexReader.buildSearchRequest(leftX, rightX, topY, bottomY, zoom, searchFilter);
for (String f : files.keySet()) { for (BinaryMapIndexReader c : files.values()) {
if (f.toLowerCase().contains(BASEMAP_NAME)) { searchRequest.clearSearchResults();
basemapSearch = true;
break;
}
}
}
for (String mapName : files.keySet()) {
if (basemapSearch && !mapName.toLowerCase().contains(BASEMAP_NAME)) {
continue;
}
BinaryMapIndexReader c = files.get(mapName);
searchRequest = BinaryMapIndexReader.buildSearchRequest(leftX, rightX, topY, bottomY, zoom, searchFilter);
List<BinaryMapDataObject> res = c.searchMapIndex(searchRequest); List<BinaryMapDataObject> res = c.searchMapIndex(searchRequest);
for (BinaryMapDataObject r : res) { for (BinaryMapDataObject r : res) {
if (PerformanceFlags.checkForDuplicateObjectIds) { if (PerformanceFlags.checkForDuplicateObjectIds) {
if (ids.contains(r.getId()) && r.getId() > 0) { if (ids.contains(r.getId()) && r.getId() > 0) {
// do not add object twice // do not add object twice
continue; continue;
}
ids.add(r.getId());
} }
ids.add(r.getId()); count++;
}
count++;
if(r.containsType(r.getMapIndex().coastlineEncodingType)){ if (r.containsType(r.getMapIndex().coastlineEncodingType)) {
coastLines.add(r); if(c.isBasemap()){
} else { basemapCoastLines.add(r);
// do not mess coastline and other types } else {
tempList.add(r); coastLines.add(r);
} }
if (checkWhetherInterrupted()) { } else {
return false; // do not mess coastline and other types
if(c.isBasemap()){
basemapResult.add(r);
} else {
tempResult.add(r);
}
}
if (checkWhetherInterrupted()) {
return false;
}
} }
if(searchRequest.isOcean() ){
mi = c.getMapIndexes().get(0);
ocean = true;
} else if(searchRequest.isLand()) {
mi = c.getMapIndexes().get(0);
} }
} }
String coastlineTime = ""; String coastlineTime = "";
boolean addBasemapCoastlines = zoom <= BASEMAP_ZOOM;
boolean emptyData = zoom > BASEMAP_ZOOM && tempResult.isEmpty() && coastLines.isEmpty() ;
if(!coastLines.isEmpty()) { if(!coastLines.isEmpty()) {
long ms = System.currentTimeMillis(); long ms = System.currentTimeMillis();
List<BinaryMapDataObject> pcoastlines = processCoastlines(coastLines, leftX, rightX, bottomY, topY, zoom,
List<BinaryMapDataObject> pcoastlines = processCoastlines(coastLines, leftX, rightX, bottomY, topY, zoom); basemapCoastLines.isEmpty());
tempList.addAll(pcoastlines); addBasemapCoastlines = pcoastlines.isEmpty() || addBasemapCoastlines;
tempResult.addAll(pcoastlines);
coastlineTime = "(coastline " + (System.currentTimeMillis() - ms) + " ms )";
} else if(basemapCoastLines.isEmpty() && mi != null){
BinaryMapDataObject o = new BinaryMapDataObject(new int[] { leftX, topY, rightX, topY, rightX, bottomY, leftX, bottomY, leftX,
topY }, new int[] { ocean ? mi.coastlineEncodingType : (mi.landEncodingType) }, null, -1);
o.setMapIndex(mi);
tempResult.add(o);
}
if(addBasemapCoastlines){
long ms = System.currentTimeMillis();
List<BinaryMapDataObject> pcoastlines = processCoastlines(basemapCoastLines, leftX, rightX, bottomY, topY, zoom, true);
tempResult.addAll(pcoastlines);
coastlineTime = "(coastline " + (System.currentTimeMillis() - ms) + " ms )"; coastlineTime = "(coastline " + (System.currentTimeMillis() - ms) + " ms )";
} }
if(emptyData && tempResult.size() > 0){
BinaryMapDataObject o = tempResult.get(0);
o.putObjectName(o.getMapIndex().nameEncodingType, context.getString(R.string.switch_to_raster_map_to_see));
}
if(zoom <= BASEMAP_ZOOM || tempResult.isEmpty()) {
tempResult.addAll(basemapResult);
}
if (count > 0) { if (count > 0) {
log.info(String.format("BLat=%s, TLat=%s, LLong=%s, RLong=%s, zoom=%s", //$NON-NLS-1$ log.info(String.format("BLat=%s, TLat=%s, LLong=%s, RLong=%s, zoom=%s", //$NON-NLS-1$
cBottomLatitude, cTopLatitude, cLeftLongitude, cRightLongitude, zoom)); cBottomLatitude, cTopLatitude, cLeftLongitude, cRightLongitude, zoom));
@ -397,7 +412,7 @@ public class MapRenderRepositories {
} }
cObjects = tempList; cObjects = tempResult;
cObjectsBox = dataBox; cObjectsBox = dataBox;
} catch (IOException e) { } catch (IOException e) {
log.debug("Search failed", e); //$NON-NLS-1$ log.debug("Search failed", e); //$NON-NLS-1$
@ -484,6 +499,7 @@ public class MapRenderRepositories {
} else { } else {
cNativeObjects = null; cNativeObjects = null;
loaded = loadVectorData(dataBox, requestedBox.getZoom(), renderingReq, nightMode); loaded = loadVectorData(dataBox, requestedBox.getZoom(), renderingReq, nightMode);
} }
if (!loaded || checkWhetherInterrupted()) { if (!loaded || checkWhetherInterrupted()) {
return; return;
@ -629,7 +645,7 @@ public class MapRenderRepositories {
/// MULTI POLYGONS (coastline) /// MULTI POLYGONS (coastline)
private List<BinaryMapDataObject> processCoastlines(List<BinaryMapDataObject> coastLines, int leftX, int rightX, private List<BinaryMapDataObject> processCoastlines(List<BinaryMapDataObject> coastLines, int leftX, int rightX,
int bottomY, int topY, int zoom) { int bottomY, int topY, int zoom, boolean showIncompleted) {
List<TLongList> completedRings = new ArrayList<TLongList>(); List<TLongList> completedRings = new ArrayList<TLongList>();
List<TLongList> uncompletedRings = new ArrayList<TLongList>(); List<TLongList> uncompletedRings = new ArrayList<TLongList>();
List<BinaryMapDataObject> result = new ArrayList<BinaryMapDataObject>(coastLines.size()); List<BinaryMapDataObject> result = new ArrayList<BinaryMapDataObject>(coastLines.size());
@ -673,6 +689,11 @@ public class MapRenderRepositories {
if (uncompletedRings.size() > 0) { if (uncompletedRings.size() > 0) {
unifyIncompletedRings(uncompletedRings, completedRings, leftX, rightX, bottomY, topY, dbId, zoom); unifyIncompletedRings(uncompletedRings, completedRings, leftX, rightX, bottomY, topY, dbId, zoom);
} }
if(!showIncompleted && uncompletedRings.size() > 0){
result.clear();
return result;
}
boolean clockwiseFound = false; boolean clockwiseFound = false;
long mask = 0xffffffffl; long mask = 0xffffffffl;
for (int i = 0; i < completedRings.size(); i++) { for (int i = 0; i < completedRings.size(); i++) {

View file

@ -2,7 +2,6 @@ package net.osmand.plus.render;
import net.osmand.access.AccessibleToast; import net.osmand.access.AccessibleToast;
import net.osmand.osm.MapUtils; import net.osmand.osm.MapUtils;
import net.osmand.plus.R;
import net.osmand.plus.ResourceManager; import net.osmand.plus.ResourceManager;
import net.osmand.plus.RotatedTileBox; import net.osmand.plus.RotatedTileBox;
import net.osmand.plus.views.BaseMapLayer; import net.osmand.plus.views.BaseMapLayer;
@ -14,7 +13,6 @@ import android.graphics.Paint;
import android.graphics.PointF; import android.graphics.PointF;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.widget.Toast;
public class MapVectorLayer extends BaseMapLayer { public class MapVectorLayer extends BaseMapLayer {
@ -104,14 +102,6 @@ public class MapVectorLayer extends BaseMapLayer {
pixRect.set(-view.getWidth() / 3, -view.getHeight() / 4, 4 * view.getWidth() / 3, 5 * view.getHeight() / 4); pixRect.set(-view.getWidth() / 3, -view.getHeight() / 4, 4 * view.getWidth() / 3, 5 * view.getHeight() / 4);
updateRotatedTileBox(); updateRotatedTileBox();
resourceManager.updateRendererMap(rotatedTileBox); resourceManager.updateRendererMap(rotatedTileBox);
// does it slow down Map refreshing ?
// Arguments : 1. Map request to read data slows whole process // 2. It works in operating memory
if (warningToSwitchMapShown < 3) {
if (!resourceManager.getRenderer().containsLatLonMapData(view.getLatitude(), view.getLongitude(), view.getZoom())) {
AccessibleToast.makeText(view.getContext(), R.string.switch_to_raster_map_to_see, Toast.LENGTH_LONG).show();
warningToSwitchMapShown++;
}
}
} }
} }