Proccess incompleted tiles
This commit is contained in:
parent
453747920e
commit
5eb925c0cb
12 changed files with 260 additions and 160 deletions
|
@ -12,8 +12,8 @@ public class ToDoConstants {
|
|||
|
||||
// Map QuadTree (skip small areas!!!)
|
||||
// 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))
|
||||
|
||||
// Render : different texts support render.xml
|
||||
|
|
|
@ -46,13 +46,7 @@ public class BinaryInspector {
|
|||
public static void main(String[] args) throws IOException {
|
||||
inspector(args);
|
||||
// test cases show info
|
||||
// inspector(new String[]{"/home/victor/projects/OsmAnd/temp/Belarus_europe.obf"});
|
||||
// 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"*/});
|
||||
|
||||
inspector(new String[]{"/home/victor/projects/OsmAnd/data/osm-gen/basemap_coastlines"});
|
||||
|
||||
|
||||
// test case extract parts
|
||||
|
@ -519,7 +513,7 @@ public class BinaryInspector {
|
|||
continue;
|
||||
// throw new NullPointerException("Type " + obj.getAdditionalTypes()[j] + "was not found");
|
||||
}
|
||||
b.append(pair.toSimpleString()+"("+types[j]+")");
|
||||
b.append(pair.toSimpleString()+" ("+types[j]+")");
|
||||
}
|
||||
b.append("]");
|
||||
if(obj.getAdditionalTypes() != null && obj.getAdditionalTypes().length > 0){
|
||||
|
|
|
@ -57,6 +57,13 @@ public class BinaryMapDataObject {
|
|||
return objectNames;
|
||||
}
|
||||
|
||||
public void putObjectName(int type, String name){
|
||||
if(objectNames == null){
|
||||
objectNames = new TIntObjectHashMap<String>();
|
||||
}
|
||||
objectNames.put(type, name);
|
||||
}
|
||||
|
||||
public int[][] getPolygonInnerCoordinates() {
|
||||
return polygonInnerCoordinates;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ public class BinaryMapIndexReader {
|
|||
private int version;
|
||||
private long dateCreated;
|
||||
// keep them immutable inside
|
||||
private boolean basemap = false;
|
||||
private List<MapIndex> mapIndexes = new ArrayList<MapIndex>();
|
||||
private List<PoiRegion> poiIndexes = new ArrayList<PoiRegion>();
|
||||
private List<AddressRegion> addressIndexes = new ArrayList<AddressRegion>();
|
||||
|
@ -72,6 +73,8 @@ public class BinaryMapIndexReader {
|
|||
private final BinaryMapPoiReaderAdapter poiAdapter;
|
||||
private final BinaryMapAddressReaderAdapter addressAdapter;
|
||||
|
||||
private static String BASEMAP_NAME = "basemap";
|
||||
|
||||
|
||||
public BinaryMapIndexReader(final RandomAccessFile raf) throws IOException {
|
||||
this(raf, false);
|
||||
|
@ -90,6 +93,7 @@ public class BinaryMapIndexReader {
|
|||
addressIndexes = new ArrayList<AddressRegion>(referenceToSameFile.addressIndexes);
|
||||
transportIndexes = new ArrayList<TransportIndex>(referenceToSameFile.transportIndexes);
|
||||
indexes = new ArrayList<BinaryIndexPart>(referenceToSameFile.indexes);
|
||||
basemap = referenceToSameFile.basemap;
|
||||
}
|
||||
|
||||
public BinaryMapIndexReader(final RandomAccessFile raf, boolean readOnlyMapData) throws IOException {
|
||||
|
@ -136,6 +140,7 @@ public class BinaryMapIndexReader {
|
|||
mapIndex.filePointer = codedIS.getTotalBytesRead();
|
||||
int oldLimit = codedIS.pushLimit(mapIndex.length);
|
||||
readMapIndex(mapIndex);
|
||||
basemap = basemap || mapIndex.isBaseMap();
|
||||
codedIS.popLimit(oldLimit);
|
||||
codedIS.seek(mapIndex.filePointer + mapIndex.length);
|
||||
mapIndexes.add(mapIndex);
|
||||
|
@ -215,6 +220,14 @@ public class BinaryMapIndexReader {
|
|||
return indexes;
|
||||
}
|
||||
|
||||
public List<MapIndex> getMapIndexes() {
|
||||
return mapIndexes;
|
||||
}
|
||||
|
||||
public boolean isBasemap() {
|
||||
return basemap;
|
||||
}
|
||||
|
||||
public boolean containsMapData(){
|
||||
return mapIndexes.size() > 0;
|
||||
}
|
||||
|
@ -668,6 +681,13 @@ public class BinaryMapIndexReader {
|
|||
case MapDataBox.TOP_FIELD_NUMBER :
|
||||
tree.top = codedIS.readSInt32() + atop;
|
||||
break;
|
||||
case MapDataBox.OCEAN_FIELD_NUMBER :
|
||||
if(codedIS.readBool()) {
|
||||
tree.ocean = Boolean.TRUE;
|
||||
} else {
|
||||
tree.ocean = Boolean.FALSE;
|
||||
}
|
||||
break;
|
||||
case MapDataBox.SHIFTTOMAPDATA_FIELD_NUMBER :
|
||||
tree.mapDataBlock = readInt() + tree.filePointer;
|
||||
break;
|
||||
|
@ -852,7 +872,12 @@ public class BinaryMapIndexReader {
|
|||
foundSubtrees.add(current);
|
||||
break;
|
||||
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;
|
||||
case MapDataBox.BOXES_FIELD_NUMBER :
|
||||
// left, ... already initialized
|
||||
|
@ -860,8 +885,8 @@ public class BinaryMapIndexReader {
|
|||
child.length = readInt();
|
||||
child.filePointer = codedIS.getTotalBytesRead();
|
||||
int oldLimit = codedIS.pushLimit(child.length);
|
||||
if(current.ocean){
|
||||
child.ocean = true;
|
||||
if(current.ocean != null ){
|
||||
child.ocean = current.ocean;
|
||||
}
|
||||
searchMapTreeBounds(child, current, req, foundSubtrees);
|
||||
codedIS.popLimit(oldLimit);
|
||||
|
@ -1228,6 +1253,9 @@ public class BinaryMapIndexReader {
|
|||
|
||||
public static class SearchRequest<T> {
|
||||
private List<T> searchResults = new ArrayList<T>();
|
||||
private boolean land = false;
|
||||
private boolean ocean = false;
|
||||
|
||||
private ResultMatcher<T> resultMatcher;
|
||||
|
||||
// 31 zoom tiles
|
||||
|
@ -1276,6 +1304,14 @@ public class BinaryMapIndexReader {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected void publishOceanTile(boolean ocean){
|
||||
if(ocean) {
|
||||
this.ocean = true;
|
||||
} else {
|
||||
this.land = true;
|
||||
}
|
||||
}
|
||||
|
||||
public List<T> getSearchResults() {
|
||||
return searchResults;
|
||||
}
|
||||
|
@ -1294,11 +1330,21 @@ public class BinaryMapIndexReader {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isOcean() {
|
||||
return ocean;
|
||||
}
|
||||
|
||||
public boolean isLand() {
|
||||
return land;
|
||||
}
|
||||
|
||||
public void clearSearchResults(){
|
||||
// recreate whole list to allow GC collect old data
|
||||
searchResults = new ArrayList<T>();
|
||||
cacheCoordinates.clear();
|
||||
cacheTypes.clear();
|
||||
land = false;
|
||||
ocean = false;
|
||||
numberOfVisitedObjects = 0;
|
||||
numberOfAcceptedObjects = 0;
|
||||
numberOfReadSubtrees = 0;
|
||||
|
@ -1331,8 +1377,13 @@ public class BinaryMapIndexReader {
|
|||
}
|
||||
|
||||
public void finishInitializingTags() {
|
||||
coastlineBrokenEncodingType = decodingRules.size() * 2 + 1;
|
||||
int free = decodingRules.size() * 2 + 1;
|
||||
coastlineBrokenEncodingType = free++;
|
||||
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) {
|
||||
|
@ -1366,7 +1417,10 @@ public class BinaryMapIndexReader {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isBaseMap(){
|
||||
return name != null && name.toLowerCase().contains(BASEMAP_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TagValuePair {
|
||||
|
@ -1455,7 +1509,7 @@ public class BinaryMapIndexReader {
|
|||
int length = 0;
|
||||
|
||||
long mapDataBlock = 0;
|
||||
boolean ocean = false;
|
||||
Boolean ocean = null;
|
||||
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
|
@ -1482,6 +1536,12 @@ public class BinaryMapIndexReader {
|
|||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -196,7 +196,6 @@ public class BinaryMapIndexWriter {
|
|||
codedOutStream.writeInt32(OsmandOdb.OsmAndMapIndex.MapRootLevel.RIGHT_FIELD_NUMBER, rightX);
|
||||
codedOutStream.writeInt32(OsmandOdb.OsmAndMapIndex.MapRootLevel.TOP_FIELD_NUMBER, topY);
|
||||
codedOutStream.writeInt32(OsmandOdb.OsmAndMapIndex.MapRootLevel.BOTTOM_FIELD_NUMBER, bottomY);
|
||||
|
||||
stackBounds.push(new Bounds(leftX, rightX, topY, bottomY));
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import java.io.FileNotFoundException;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.Iterator;
|
||||
|
@ -17,14 +16,12 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
import net.osmand.Algoritms;
|
||||
import net.osmand.binary.OsmandOdb.MapData;
|
||||
import net.osmand.binary.OsmandOdb.MapDataBlock;
|
||||
import net.osmand.binary.OsmandOdb.MapDataBlock.Builder;
|
||||
import net.osmand.data.MapAlgorithms;
|
||||
import net.osmand.data.preparation.MapZooms.MapZoomPair;
|
||||
import net.osmand.osm.Entity;
|
||||
|
@ -54,20 +51,21 @@ public class CoastlineProcessor {
|
|||
public static final byte TILE_ZOOMLEVEL = 12;
|
||||
private static final byte BITMASK = 0x3;
|
||||
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 MapRenderingTypes renderingTypes;
|
||||
private final MapZooms mapZooms;
|
||||
private final Log logMapDataWarn;
|
||||
private SimplisticQuadTree quadTree;
|
||||
private SimplisticQuadTree[] quadTrees;
|
||||
|
||||
private static class SimplisticQuadTree {
|
||||
public boolean ocean;
|
||||
public boolean land;
|
||||
int zoom;
|
||||
int x;
|
||||
int y;
|
||||
boolean ocean;
|
||||
boolean land;
|
||||
|
||||
public SimplisticQuadTree(int x, int y, int zoom) {
|
||||
this.x = x;
|
||||
|
@ -76,7 +74,8 @@ public class CoastlineProcessor {
|
|||
}
|
||||
|
||||
SimplisticQuadTree[] children = null;
|
||||
List<Way> coastlines = null;
|
||||
Map<MapZoomPair,List<Way>> coastlines = null;
|
||||
|
||||
|
||||
public SimplisticQuadTree[] getAllChildren(){
|
||||
initChildren();
|
||||
|
@ -87,11 +86,23 @@ public class CoastlineProcessor {
|
|||
return children != null;
|
||||
}
|
||||
|
||||
public void addCoastline(Way w){
|
||||
public void addCoastline(MapZoomPair p, Way w){
|
||||
|
||||
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) {
|
||||
|
@ -127,10 +138,15 @@ public class CoastlineProcessor {
|
|||
this.mapZooms = mapZooms;
|
||||
this.renderingTypes = renderingTypes;
|
||||
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 {
|
||||
|
||||
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) {
|
||||
int x1 = x >> (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) {
|
||||
int x1 = x >> (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);
|
||||
|
||||
BitSet seaTileInfo = new BitSet(BITS_COUNT);
|
||||
BitSet landTileInfo = new BitSet(BITS_COUNT);
|
||||
constructBitSetInfo(seaTileInfo, landTileInfo);
|
||||
|
||||
int baseZoom = 4;
|
||||
int tiles = 1 << baseZoom;
|
||||
ArrayList<SimplisticQuadTree> toVisit = new ArrayList<SimplisticQuadTree>();
|
||||
int cnt = 0;
|
||||
for (int x = 0; x < tiles; x++) {
|
||||
for (int y = 0; y < tiles; y++) {
|
||||
toVisit.add(rootTree.getOrCreateSubTree(x, y, baseZoom));
|
||||
}
|
||||
}
|
||||
int ntc = 0;
|
||||
for (int zoom = baseZoom; zoom <= TILE_ZOOMLEVEL && !toVisit.isEmpty(); zoom++) {
|
||||
cnt = 0;
|
||||
initializeQuadTree(rootTree, baseZoom, maxZoom, toVisit);
|
||||
return rootTree;
|
||||
|
||||
}
|
||||
|
||||
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>();
|
||||
for (SimplisticQuadTree subtree : toVisit) {
|
||||
int x = subtree.x;
|
||||
int y = subtree.y;
|
||||
if (isWaterTile(seaTileInfo, x, y, zoom)) {
|
||||
cnt++;
|
||||
if (isWaterTile(x, y, zoom)) {
|
||||
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;
|
||||
cnt++;
|
||||
} else if(zoom < TILE_ZOOMLEVEL){
|
||||
SimplisticQuadTree[] vis = rootTree.getOrCreateSubTree(x, y, zoom).getOrCreateSubTree(x, y, zoom)
|
||||
.getAllChildren();
|
||||
for (SimplisticQuadTree t : vis) {
|
||||
newToVisit.add(t);
|
||||
}
|
||||
} else {
|
||||
ntc ++;
|
||||
}
|
||||
}
|
||||
// System.out.println(" Zoom " + zoom + " count " + cnt);
|
||||
toVisit = newToVisit;
|
||||
}
|
||||
// System.out.println("Not covered " + ntc + " from " + (float) ntc / ((1 << TILE_ZOOMLEVEL) * (1<<TILE_ZOOMLEVEL)));
|
||||
return rootTree;
|
||||
|
||||
return toVisit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void writeCoastlinesFile(BinaryMapIndexWriter writer) throws IOException {
|
||||
writeCoastlinesFile(writer, quadTree);
|
||||
}
|
||||
|
||||
private void writeCoastlinesFile(BinaryMapIndexWriter writer, SimplisticQuadTree simplisticQuadTree) throws IOException {
|
||||
writer.startWriteMapIndex("Coastline");
|
||||
public void writeCoastlinesFile(BinaryMapIndexWriter writer, String regionName) throws IOException {
|
||||
writer.startWriteMapIndex(regionName);
|
||||
// write map encoding rules
|
||||
writer.writeMapEncodingRules(renderingTypes.getEncodingRuleTypes());
|
||||
|
||||
// TODO zooms file iterate in cycle
|
||||
MapZoomPair p = mapZooms.getLevels().get(mapZooms.getLevels().size() - 1);
|
||||
// write map levels and map index
|
||||
writer.startWriteMapLevelIndex(p.getMinZoom(), p.getMinZoom(), 0, 0, (1 << 31) - 1, (1 << 31) - 1);
|
||||
|
||||
Map<SimplisticQuadTree, BinaryFileReference> refs = new LinkedHashMap<CoastlineProcessor.SimplisticQuadTree, BinaryFileReference>();
|
||||
writeBinaryMapTree(simplisticQuadTree, writer, refs);
|
||||
int i = 0;
|
||||
for (MapZoomPair p : mapZooms.getLevels()) {
|
||||
// write map levels and map index
|
||||
writer.startWriteMapLevelIndex(p.getMinZoom(), p.getMaxZoom(), 0, (1 << 31) - 1, 0, (1 << 31) - 1);
|
||||
|
||||
// without data blocks
|
||||
writeBinaryMapBlock(simplisticQuadTree, writer, refs);
|
||||
Map<SimplisticQuadTree, BinaryFileReference> refs = new LinkedHashMap<CoastlineProcessor.SimplisticQuadTree, BinaryFileReference>();
|
||||
writeBinaryMapTree(quadTrees[i], writer, refs, p);
|
||||
|
||||
writer.endWriteMapLevelIndex();
|
||||
// without data blocks
|
||||
writeBinaryMapBlock(quadTrees[i], writer, refs, p);
|
||||
|
||||
writer.endWriteMapLevelIndex();
|
||||
i++;
|
||||
}
|
||||
writer.endWriteMapIndex();
|
||||
writer.flush();
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
TIntArrayList type = new TIntArrayList();
|
||||
type.add(renderingTypes.getCoastlineRuleType().getTargetId());
|
||||
|
@ -299,10 +307,12 @@ public class CoastlineProcessor {
|
|||
MapDataBlock.Builder dataBlock = MapDataBlock.newBuilder();
|
||||
SimplisticQuadTree quad = e.getKey();
|
||||
|
||||
for (Way w : quad.coastlines) {
|
||||
for (Way w : quad.getCoastlines(p)) {
|
||||
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();
|
||||
for (Node n : w.getNodes()) {
|
||||
for (Node n : res) {
|
||||
if (n != null) {
|
||||
int y = MapUtils.get31TileNumberY(n.getLatitude());
|
||||
int x = MapUtils.get31TileNumberX(n.getLongitude());
|
||||
|
@ -323,34 +333,40 @@ public class CoastlineProcessor {
|
|||
}
|
||||
|
||||
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 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 yB = (quadTree.y + 1) << (31 - quadTree.zoom) - 1;
|
||||
BinaryFileReference ref = writer.startMapTreeElement(xL, xR, yT, yB, false,
|
||||
quadTree.ocean, quadTree.land);
|
||||
int yB = ((quadTree.y + 1) << (31 - quadTree.zoom)) - 1;
|
||||
boolean defined = quadTree.coastlinesDefined(p);
|
||||
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) {
|
||||
refs.put(quadTree, ref);
|
||||
}
|
||||
|
||||
|
||||
if (quadTree.areChildrenDefined()) {
|
||||
SimplisticQuadTree[] allChildren = quadTree.getAllChildren();
|
||||
|
||||
for (SimplisticQuadTree ch : allChildren) {
|
||||
writeBinaryMapTree(ch, writer, refs);
|
||||
writeBinaryMapTree(ch, writer, refs, p);
|
||||
}
|
||||
}
|
||||
writer.endWriteMapTreeElement();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void processCoastline(Way e) {
|
||||
// for(MapZoomPair p : mapZooms.getLevels()) {
|
||||
renderingTypes.getCoastlineRuleType().updateFreq();
|
||||
MapZoomPair p = mapZooms.getLevels().get(mapZooms.getLevels().size() - 1);
|
||||
{
|
||||
int z = (p.getMinZoom() + p.getMaxZoom()) / 2;
|
||||
int ij = 0;
|
||||
for(MapZoomPair p : mapZooms.getLevels()) {
|
||||
SimplisticQuadTree quadTree = quadTrees[ij++];
|
||||
int z = Math.min((p.getMinZoom() + p.getMaxZoom()) / 2, p.getMinZoom() + 3);
|
||||
List<Node> ns = e.getNodes();
|
||||
if(ns.size() < 2) {
|
||||
return;
|
||||
|
@ -380,20 +396,29 @@ public class CoastlineProcessor {
|
|||
int nx31 = MapUtils.get31TileNumberX(next.getLongitude());
|
||||
int ny31 = MapUtils.get31TileNumberY(next.getLatitude());
|
||||
// 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);
|
||||
if( rightX < 0 ){
|
||||
if (rightX < 0) {
|
||||
rightX = Integer.MAX_VALUE;
|
||||
}
|
||||
int topY = (tiley << (31 - z)) - 1;
|
||||
int topY = (tiley << (31 - z)) - 1;
|
||||
int bottomY = (tiley + 1) << (31 - z);
|
||||
if( bottomY < 0 ){
|
||||
if (bottomY < 0) {
|
||||
bottomY = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
|
||||
long inter = MapAlgorithms.calculateIntersection(px31, py31, nx31, ny31, leftX, rightX, bottomY, topY);
|
||||
int cy31 = (int) inter;
|
||||
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);
|
||||
px31 = cx31;
|
||||
py31 = cy31;
|
||||
|
@ -409,16 +434,16 @@ public class CoastlineProcessor {
|
|||
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) {
|
||||
WayChain chain = null;
|
||||
|
|
|
@ -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/cuba2.osm.bz2"),
|
||||
// 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"),
|
||||
new ConsoleProgressImplementation(1), null, zooms, rt, log);
|
||||
|
||||
|
|
|
@ -98,7 +98,6 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
|
|||
}
|
||||
|
||||
public void indexMapRelationsAndMultiPolygons(Entity e, OsmDbAccessorContext ctx) throws SQLException {
|
||||
// indexHighwayRestrictions(e, ctx);
|
||||
indexMultiPolygon(e, ctx);
|
||||
}
|
||||
|
||||
|
@ -558,7 +557,7 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
|
|||
closePreparedStatements(mapBinaryStat, mapLowLevelBinaryStat);
|
||||
mapConnection.commit();
|
||||
if(COASTLINE_PROCESS) {
|
||||
coastlineProcessor.writeCoastlinesFile(writer);
|
||||
coastlineProcessor.writeCoastlinesFile(writer, regionName);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -355,6 +355,8 @@
|
|||
<filter minzoom="14" textSize="14" ref="false"/>
|
||||
</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 -->
|
||||
<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"/>
|
||||
|
|
|
@ -180,7 +180,7 @@
|
|||
\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>
|
||||
|
||||
<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="tip_day_night_mode">Day/Night Mode</string>
|
||||
|
|
|
@ -59,12 +59,12 @@ public class MapRenderRepositories {
|
|||
|
||||
private final static Log log = LogUtil.getLog(MapRenderRepositories.class);
|
||||
private final Context context;
|
||||
private final static int BASEMAP_ZOOM = 7;
|
||||
private Handler handler;
|
||||
private Map<String, BinaryMapIndexReader> files = new LinkedHashMap<String, BinaryMapIndexReader>();
|
||||
private Set<String> nativeFiles = new HashSet<String>();
|
||||
private OsmandRenderer renderer;
|
||||
|
||||
private static String BASEMAP_NAME = "basemap";
|
||||
|
||||
// lat/lon box of requested vector data
|
||||
private RectF cObjectsBox = new RectF();
|
||||
|
@ -229,8 +229,8 @@ public class MapRenderRepositories {
|
|||
}
|
||||
|
||||
public boolean basemapExists() {
|
||||
for (String f : files.keySet()) {
|
||||
if (f.toLowerCase().contains(BASEMAP_NAME)) {
|
||||
for (BinaryMapIndexReader f : files.values()) {
|
||||
if (f.isBasemap()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -245,21 +245,9 @@ public class MapRenderRepositories {
|
|||
int bottomY = MapUtils.get31TileNumberY(dataBox.bottom);
|
||||
int topY = MapUtils.get31TileNumberY(dataBox.top);
|
||||
long now = System.currentTimeMillis();
|
||||
// search lower level zooms only in basemap for now :) before it was intersection of maps on zooms 5-7
|
||||
boolean basemapSearch = false;
|
||||
if (zoom <= 7) {
|
||||
for (String f : files.keySet()) {
|
||||
if (f.toLowerCase().contains(BASEMAP_NAME)) {
|
||||
basemapSearch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO coastline/land tiles
|
||||
NativeSearchResult resultHandler = null;
|
||||
for (String mapName : files.keySet()) {
|
||||
if (basemapSearch && !mapName.toLowerCase().contains(BASEMAP_NAME)) {
|
||||
continue;
|
||||
}
|
||||
BinaryMapIndexReader reader = files.get(mapName);
|
||||
if(!reader.containsMapData(leftX, topY, rightX, bottomY, zoom)) {
|
||||
continue;
|
||||
|
@ -301,10 +289,12 @@ public class MapRenderRepositories {
|
|||
}
|
||||
try {
|
||||
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
|
||||
TLongSet ids = new TLongHashSet();
|
||||
List<BinaryMapDataObject> coastLines = new ArrayList<BinaryMapDataObject>();
|
||||
List<BinaryMapDataObject> basemapCoastLines = new ArrayList<BinaryMapDataObject>();
|
||||
int leftX = MapUtils.get31TileNumberX(cLeftLongitude);
|
||||
int rightX = MapUtils.get31TileNumberX(cRightLongitude);
|
||||
int bottomY = MapUtils.get31TileNumberY(cBottomLatitude);
|
||||
|
@ -340,56 +330,81 @@ public class MapRenderRepositories {
|
|||
if (zoom > 16) {
|
||||
searchFilter = null;
|
||||
}
|
||||
// search lower level zooms only in basemap for now :) before it was intersection of maps on zooms 5-7
|
||||
boolean basemapSearch = false;
|
||||
if (zoom <= 7) {
|
||||
for (String f : files.keySet()) {
|
||||
if (f.toLowerCase().contains(BASEMAP_NAME)) {
|
||||
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);
|
||||
boolean ocean = false;
|
||||
MapIndex mi = null;
|
||||
searchRequest = BinaryMapIndexReader.buildSearchRequest(leftX, rightX, topY, bottomY, zoom, searchFilter);
|
||||
for (BinaryMapIndexReader c : files.values()) {
|
||||
searchRequest.clearSearchResults();
|
||||
List<BinaryMapDataObject> res = c.searchMapIndex(searchRequest);
|
||||
for (BinaryMapDataObject r : res) {
|
||||
if (PerformanceFlags.checkForDuplicateObjectIds) {
|
||||
if (ids.contains(r.getId()) && r.getId() > 0) {
|
||||
// do not add object twice
|
||||
continue;
|
||||
for (BinaryMapDataObject r : res) {
|
||||
if (PerformanceFlags.checkForDuplicateObjectIds) {
|
||||
if (ids.contains(r.getId()) && r.getId() > 0) {
|
||||
// do not add object twice
|
||||
continue;
|
||||
}
|
||||
ids.add(r.getId());
|
||||
}
|
||||
ids.add(r.getId());
|
||||
}
|
||||
count++;
|
||||
count++;
|
||||
|
||||
if(r.containsType(r.getMapIndex().coastlineEncodingType)){
|
||||
coastLines.add(r);
|
||||
} else {
|
||||
// do not mess coastline and other types
|
||||
tempList.add(r);
|
||||
if (r.containsType(r.getMapIndex().coastlineEncodingType)) {
|
||||
if(c.isBasemap()){
|
||||
basemapCoastLines.add(r);
|
||||
} else {
|
||||
coastLines.add(r);
|
||||
}
|
||||
} else {
|
||||
// do not mess coastline and other types
|
||||
if(c.isBasemap()){
|
||||
basemapResult.add(r);
|
||||
} else {
|
||||
tempResult.add(r);
|
||||
}
|
||||
}
|
||||
if (checkWhetherInterrupted()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
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 = "";
|
||||
boolean addBasemapCoastlines = zoom <= BASEMAP_ZOOM;
|
||||
boolean emptyData = zoom > BASEMAP_ZOOM && tempResult.isEmpty() && coastLines.isEmpty() ;
|
||||
|
||||
if(!coastLines.isEmpty()) {
|
||||
long ms = System.currentTimeMillis();
|
||||
|
||||
List<BinaryMapDataObject> pcoastlines = processCoastlines(coastLines, leftX, rightX, bottomY, topY, zoom);
|
||||
tempList.addAll(pcoastlines);
|
||||
List<BinaryMapDataObject> pcoastlines = processCoastlines(coastLines, leftX, rightX, bottomY, topY, zoom,
|
||||
basemapCoastLines.isEmpty());
|
||||
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 )";
|
||||
}
|
||||
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) {
|
||||
log.info(String.format("BLat=%s, TLat=%s, LLong=%s, RLong=%s, zoom=%s", //$NON-NLS-1$
|
||||
cBottomLatitude, cTopLatitude, cLeftLongitude, cRightLongitude, zoom));
|
||||
|
@ -397,7 +412,7 @@ public class MapRenderRepositories {
|
|||
}
|
||||
|
||||
|
||||
cObjects = tempList;
|
||||
cObjects = tempResult;
|
||||
cObjectsBox = dataBox;
|
||||
} catch (IOException e) {
|
||||
log.debug("Search failed", e); //$NON-NLS-1$
|
||||
|
@ -484,6 +499,7 @@ public class MapRenderRepositories {
|
|||
} else {
|
||||
cNativeObjects = null;
|
||||
loaded = loadVectorData(dataBox, requestedBox.getZoom(), renderingReq, nightMode);
|
||||
|
||||
}
|
||||
if (!loaded || checkWhetherInterrupted()) {
|
||||
return;
|
||||
|
@ -629,7 +645,7 @@ public class MapRenderRepositories {
|
|||
|
||||
/// MULTI POLYGONS (coastline)
|
||||
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> uncompletedRings = new ArrayList<TLongList>();
|
||||
List<BinaryMapDataObject> result = new ArrayList<BinaryMapDataObject>(coastLines.size());
|
||||
|
@ -673,6 +689,11 @@ public class MapRenderRepositories {
|
|||
if (uncompletedRings.size() > 0) {
|
||||
unifyIncompletedRings(uncompletedRings, completedRings, leftX, rightX, bottomY, topY, dbId, zoom);
|
||||
}
|
||||
if(!showIncompleted && uncompletedRings.size() > 0){
|
||||
result.clear();
|
||||
return result;
|
||||
|
||||
}
|
||||
boolean clockwiseFound = false;
|
||||
long mask = 0xffffffffl;
|
||||
for (int i = 0; i < completedRings.size(); i++) {
|
||||
|
|
|
@ -2,7 +2,6 @@ package net.osmand.plus.render;
|
|||
|
||||
import net.osmand.access.AccessibleToast;
|
||||
import net.osmand.osm.MapUtils;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.ResourceManager;
|
||||
import net.osmand.plus.RotatedTileBox;
|
||||
import net.osmand.plus.views.BaseMapLayer;
|
||||
|
@ -14,7 +13,6 @@ import android.graphics.Paint;
|
|||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.widget.Toast;
|
||||
|
||||
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);
|
||||
updateRotatedTileBox();
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue