mapsforge file reader:

- add support for file version 3 back
- project POIs
- fix sync of shared Header and Index
This commit is contained in:
Hannes Janetzek 2013-03-09 16:32:56 +01:00
parent c82026fa6e
commit 179212affc
3 changed files with 105 additions and 81 deletions

View File

@ -16,6 +16,7 @@ package org.oscim.database.mapfile;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -53,7 +54,7 @@ class IndexCache {
*/ */
IndexCache(RandomAccessFile randomAccessFile, int capacity) { IndexCache(RandomAccessFile randomAccessFile, int capacity) {
this.randomAccessFile = randomAccessFile; this.randomAccessFile = randomAccessFile;
this.map = new LRUCache<IndexCacheEntryKey, byte[]>(capacity); this.map = Collections.synchronizedMap(new LRUCache<IndexCacheEntryKey, byte[]>(capacity));
} }
/** /**
@ -75,7 +76,7 @@ class IndexCache {
* the number of the block in the map file. * the number of the block in the map file.
* @return the index entry or -1 if the block number is invalid. * @return the index entry or -1 if the block number is invalid.
*/ */
long getIndexEntry(SubFileParameter subFileParameter, long blockNumber) { synchronized long getIndexEntry(SubFileParameter subFileParameter, long blockNumber) {
try { try {
// check if the block number is out of bounds // check if the block number is out of bounds
if (blockNumber >= subFileParameter.numberOfBlocks) { if (blockNumber >= subFileParameter.numberOfBlocks) {

View File

@ -203,6 +203,8 @@ public class MapDatabase implements IMapDatabase {
private int minLat, minLon; private int minLat, minLon;
private Tile mTile; private Tile mTile;
private static boolean sMapExperimental;
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.oscim.map.reader.IMapDatabase#executeQuery(org.oscim.core.Tile, * @see org.oscim.map.reader.IMapDatabase#executeQuery(org.oscim.core.Tile,
@ -221,7 +223,7 @@ public class MapDatabase implements IMapDatabase {
try { try {
mTile = tile; mTile = tile;
// prepareExecution();
QueryParameters queryParameters = new QueryParameters(); QueryParameters queryParameters = new QueryParameters();
queryParameters.queryZoomLevel = sMapFileHeader queryParameters.queryZoomLevel = sMapFileHeader
.getQueryZoomLevel(tile.zoomLevel); .getQueryZoomLevel(tile.zoomLevel);
@ -258,7 +260,7 @@ public class MapDatabase implements IMapDatabase {
@Override @Override
public String getMapProjection() { public String getMapProjection() {
return "WSG84"; // getMapFileInfo().projectionName; return "WSG84";
} }
/* /*
@ -282,7 +284,7 @@ public class MapDatabase implements IMapDatabase {
} }
// make sure to close any previously opened file first // make sure to close any previously opened file first
close(); //close();
File file = new File(options.get("file")); File file = new File(options.get("file"));
@ -304,8 +306,8 @@ public class MapDatabase implements IMapDatabase {
mFileSize = mInputFile.length(); mFileSize = mInputFile.length();
mReadBuffer = new ReadBuffer(mInputFile); mReadBuffer = new ReadBuffer(mInputFile);
if (instances > 0) { Log.d(TAG, "open instance " + instances + " " + file.getAbsolutePath());
instances++; if (instances++ > 0) {
return OpenResult.SUCCESS; return OpenResult.SUCCESS;
} }
@ -317,10 +319,10 @@ public class MapDatabase implements IMapDatabase {
return openResult; return openResult;
} }
prepareExecution(); sDatabaseIndexCache = new IndexCache(mInputFile, INDEX_CACHE_SIZE);
sMapExperimental = sMapFileHeader.getMapFileInfo().fileVersion == 4;
instances++;
Log.d(TAG, "File version: " + sMapFileHeader.getMapFileInfo().fileVersion);
return OpenResult.SUCCESS; return OpenResult.SUCCESS;
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, e.getMessage()); Log.e(TAG, e.getMessage());
@ -336,7 +338,12 @@ public class MapDatabase implements IMapDatabase {
*/ */
@Override @Override
public void close() { public void close() {
if (instances == 0)
return;
instances--; instances--;
Log.d(TAG, "close instance " + instances);
if (instances > 0) { if (instances > 0) {
mReadBuffer = null; mReadBuffer = null;
return; return;
@ -371,12 +378,6 @@ public class MapDatabase implements IMapDatabase {
} }
} }
private void prepareExecution() {
if (sDatabaseIndexCache == null) {
sDatabaseIndexCache = new IndexCache(mInputFile, INDEX_CACHE_SIZE);
}
}
/** /**
* Processes a single block and executes the callback functions on all map * Processes a single block and executes the callback functions on all map
* elements. * elements.
@ -589,6 +590,18 @@ public class MapDatabase implements IMapDatabase {
private boolean processPOIs(IMapDatabaseCallback mapDatabaseCallback, int numberOfPois) { private boolean processPOIs(IMapDatabaseCallback mapDatabaseCallback, int numberOfPois) {
Tag[] poiTags = sMapFileHeader.getMapFileInfo().poiTags; Tag[] poiTags = sMapFileHeader.getMapFileInfo().poiTags;
Tag[] tags = null; Tag[] tags = null;
Tag[] curTags;
long x = mTile.pixelX;
long y = mTile.pixelY + Tile.TILE_SIZE;
long z = Tile.TILE_SIZE << mTile.zoomLevel;
long dx = (x - (z >> 1));
long dy = (y - (z >> 1));
double divx = 180000000.0 / (z >> 1);
double divy = z / PIx4;
for (int elementCounter = numberOfPois; elementCounter != 0; --elementCounter) { for (int elementCounter = numberOfPois; elementCounter != 0; --elementCounter) {
if (mDebugFile) { if (mDebugFile) {
@ -601,8 +614,6 @@ public class MapDatabase implements IMapDatabase {
} }
} }
// Log.d("MapDatabase", "read POI");
// get the POI latitude offset (VBE-S) // get the POI latitude offset (VBE-S)
int latitude = mTileLatitude + mReadBuffer.readSignedInt(); int latitude = mTileLatitude + mReadBuffer.readSignedInt();
@ -617,29 +628,26 @@ public class MapDatabase implements IMapDatabase {
// bit 5-8 represent the number of tag IDs // bit 5-8 represent the number of tag IDs
byte numberOfTags = (byte) (specialByte & POI_NUMBER_OF_TAGS_BITMASK); byte numberOfTags = (byte) (specialByte & POI_NUMBER_OF_TAGS_BITMASK);
// boolean changed = false;
if (numberOfTags != 0) { if (numberOfTags != 0) {
tags = mReadBuffer.readTags(poiTags, numberOfTags); tags = mReadBuffer.readTags(poiTags, numberOfTags);
// changed = true;
} }
if (tags == null) if (tags == null)
return false; return false;
curTags = tags;
// get the feature bitmask (1 byte) // get the feature bitmask (1 byte)
byte featureByte = mReadBuffer.readByte(); byte featureByte = mReadBuffer.readByte();
// bit 1-3 enable optional features // bit 1-3 enable optional features
// check if the POI has a name // check if the POI has a name
if ((featureByte & POI_FEATURE_NAME) != 0) { if ((featureByte & WAY_FEATURE_NAME) != 0) {
// int pos = mReadBuffer.getPositionAndSkip();
String str = mReadBuffer.readUTF8EncodedString(); String str = mReadBuffer.readUTF8EncodedString();
Tag[] tmp = tags; curTags = new Tag[tags.length + 1];
tags = new Tag[tmp.length + 1]; System.arraycopy(tags, 0, curTags, 0, tags.length);
System.arraycopy(tmp, 0, tags, 0, tmp.length); curTags[tags.length] = new Tag(Tag.TAG_KEY_NAME, str, false);
tags[tags.length - 1] = new Tag("name", str, false);
} }
// check if the POI has a house number // check if the POI has a house number
@ -657,7 +665,11 @@ public class MapDatabase implements IMapDatabase {
// Integer.toString(mReadBuffer.readSignedInt()))); // Integer.toString(mReadBuffer.readSignedInt())));
} }
mapDatabaseCallback.renderPointOfInterest(layer, tags, latitude, longitude); longitude = (int) (longitude / divx - dx);
double sinLat = Math.sin(latitude * PI180);
latitude = (int) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
mapDatabaseCallback.renderPointOfInterest(layer, curTags, latitude, longitude);
} }
@ -809,16 +821,20 @@ public class MapDatabase implements IMapDatabase {
int numberOfWays) { int numberOfWays) {
Tag[] tags = null; Tag[] tags = null;
Tag[] curTags;
Tag[] wayTags = sMapFileHeader.getMapFileInfo().wayTags; Tag[] wayTags = sMapFileHeader.getMapFileInfo().wayTags;
int[] textPos = new int[3];
// float[] labelPosition;
// boolean skippedWays = false;
int wayDataBlocks; int wayDataBlocks;
// skip string block // skip string block
int stringsSize = mReadBuffer.readUnsignedInt(); int stringsSize = 0;
stringOffset = 0;
if (sMapExperimental) {
stringsSize = mReadBuffer.readUnsignedInt();
stringOffset = mReadBuffer.getBufferPosition(); stringOffset = mReadBuffer.getBufferPosition();
mReadBuffer.skipBytes(stringsSize); mReadBuffer.skipBytes(stringsSize);
}
for (int elementCounter = numberOfWays; elementCounter != 0; --elementCounter) { for (int elementCounter = numberOfWays; elementCounter != 0; --elementCounter) {
if (mDebugFile) { if (mDebugFile) {
@ -841,7 +857,7 @@ public class MapDatabase implements IMapDatabase {
if (elementCounter < 0) if (elementCounter < 0)
return false; return false;
if (mReadBuffer.lastTagPosition > 0) { if (sMapExperimental && mReadBuffer.lastTagPosition > 0) {
int pos = mReadBuffer.getBufferPosition(); int pos = mReadBuffer.getBufferPosition();
mReadBuffer.setBufferPosition(mReadBuffer.lastTagPosition); mReadBuffer.setBufferPosition(mReadBuffer.lastTagPosition);
@ -851,8 +867,6 @@ public class MapDatabase implements IMapDatabase {
if (tags == null) if (tags == null)
return false; return false;
// skippedWays = true;
mReadBuffer.setBufferPosition(pos); mReadBuffer.setBufferPosition(pos);
} }
} else { } else {
@ -862,7 +876,7 @@ public class MapDatabase implements IMapDatabase {
if (mDebugFile) { if (mDebugFile) {
Log.w(TAG, DEBUG_SIGNATURE_BLOCK + mSignatureBlock); Log.w(TAG, DEBUG_SIGNATURE_BLOCK + mSignatureBlock);
} }
Log.w(TAG, "EEEEEK way... 2"); Log.e(TAG, "BUG way 2");
return false; return false;
} }
@ -878,57 +892,64 @@ public class MapDatabase implements IMapDatabase {
// bit 5-8 represent the number of tag IDs // bit 5-8 represent the number of tag IDs
byte numberOfTags = (byte) (specialByte & WAY_NUMBER_OF_TAGS_BITMASK); byte numberOfTags = (byte) (specialByte & WAY_NUMBER_OF_TAGS_BITMASK);
// boolean changed = skippedWays; if (numberOfTags != 0)
// skippedWays = false;
if (numberOfTags != 0) {
tags = mReadBuffer.readTags(wayTags, numberOfTags); tags = mReadBuffer.readTags(wayTags, numberOfTags);
// changed = true;
}
if (tags == null) if (tags == null)
return false; return false;
curTags = tags;
// get the feature bitmask (1 byte) // get the feature bitmask (1 byte)
byte featureByte = mReadBuffer.readByte(); byte featureByte = mReadBuffer.readByte();
// bit 1-6 enable optional features // bit 1-6 enable optional features
boolean featureWayDoubleDeltaEncoding = (featureByte & WAY_FEATURE_DOUBLE_DELTA_ENCODING) != 0; boolean featureWayDoubleDeltaEncoding = (featureByte & WAY_FEATURE_DOUBLE_DELTA_ENCODING) != 0;
if (sMapExperimental) {
// check if the way has a name // check if the way has a name
if ((featureByte & WAY_FEATURE_NAME) != 0) { if ((featureByte & WAY_FEATURE_NAME) != 0) {
textPos[0] = mReadBuffer.readUnsignedInt(); int textPos = mReadBuffer.readUnsignedInt();
// String str = String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos);
mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos[0]);
// if (changed) { curTags = new Tag[tags.length + 1];
// Tag[] tmp = tags; System.arraycopy(tags, 0, curTags, 0, tags.length);
// tags = new Tag[tmp.length + 1]; curTags[tags.length] = new Tag(Tag.TAG_KEY_NAME, str, false);
// System.arraycopy(tmp, 0, tags, 0, tmp.length);
// }
// tags[tags.length - 1] = new Tag(Tag.TAG_KEY_NAME, str,
// false);
} }
else
textPos[0] = -1;
// check if the way has a house number // check if the way has a house number
if ((featureByte & WAY_FEATURE_HOUSE_NUMBER) != 0) { if ((featureByte & WAY_FEATURE_HOUSE_NUMBER) != 0) {
textPos[1] = mReadBuffer.readUnsignedInt(); //int textPos =
mReadBuffer.readUnsignedInt();
} }
else
textPos[1] = -1;
// check if the way has a reference // check if the way has a reference
if ((featureByte & WAY_FEATURE_REF) != 0) if ((featureByte & WAY_FEATURE_REF) != 0) {
textPos[2] = mReadBuffer.readUnsignedInt(); //int textPos =
else mReadBuffer.readUnsignedInt();
textPos[2] = -1; }
} else {
if ((featureByte & WAY_FEATURE_NAME) != 0) {
String str = mReadBuffer.readUTF8EncodedString();
curTags = new Tag[tags.length + 1];
System.arraycopy(tags, 0, curTags, 0, tags.length);
curTags[tags.length] = new Tag(Tag.TAG_KEY_NAME, str, false);
}
// check if the way has a house number
if ((featureByte & WAY_FEATURE_HOUSE_NUMBER) != 0) {
String str = mReadBuffer.readUTF8EncodedString();
}
// check if the way has a reference
if ((featureByte & WAY_FEATURE_REF) != 0) {
String str = mReadBuffer.readUTF8EncodedString();
}
}
if ((featureByte & WAY_FEATURE_LABEL_POSITION) != 0) if ((featureByte & WAY_FEATURE_LABEL_POSITION) != 0)
// labelPosition = // labelPosition =
readOptionalLabelPosition(); readOptionalLabelPosition();
// else
// labelPosition = null;
if ((featureByte & WAY_FEATURE_DATA_BLOCKS_BYTE) != 0) { if ((featureByte & WAY_FEATURE_DATA_BLOCKS_BYTE) != 0) {
wayDataBlocks = mReadBuffer.readUnsignedInt(); wayDataBlocks = mReadBuffer.readUnsignedInt();
@ -954,7 +975,7 @@ public class MapDatabase implements IMapDatabase {
&& mWayNodes[1] == mWayNodes[l - 1]; && mWayNodes[1] == mWayNodes[l - 1];
projectToTile(mWayNodes, wayLengths); projectToTile(mWayNodes, wayLengths);
mapDatabaseCallback.renderWay(layer, tags, mWayNodes, wayLengths, closed, 0); mapDatabaseCallback.renderWay(layer, curTags, mWayNodes, wayLengths, closed, 0);
} }
} }
@ -1068,7 +1089,7 @@ public class MapDatabase implements IMapDatabase {
cnt += 2; cnt += 2;
} }
if (coords[first] == coords[outPos-2] && coords[first+1] == coords[outPos-1]){ if (coords[first] == coords[outPos - 2] && coords[first + 1] == coords[outPos - 1]) {
//Log.d(TAG, "drop closed"); //Log.d(TAG, "drop closed");
indices[i] = (short) (cnt - 2); indices[i] = (short) (cnt - 2);
outPos -= 2; outPos -= 2;
@ -1079,4 +1100,5 @@ public class MapDatabase implements IMapDatabase {
return true; return true;
} }
} }

View File

@ -50,7 +50,8 @@ final class RequiredFields {
/** /**
* Version of the map file format which is supported by this implementation. * Version of the map file format which is supported by this implementation.
*/ */
private static final int SUPPORTED_FILE_VERSION = 4; private static final int FILE_VERSION_3 = 3;
private static final int FILE_VERSION_4 = 4;
/** /**
* The maximum latitude values in microdegrees. * The maximum latitude values in microdegrees.
@ -123,7 +124,7 @@ final class RequiredFields {
static OpenResult readFileVersion(ReadBuffer readBuffer, MapFileInfoBuilder mapFileInfoBuilder) { static OpenResult readFileVersion(ReadBuffer readBuffer, MapFileInfoBuilder mapFileInfoBuilder) {
// get and check the file version (4 bytes) // get and check the file version (4 bytes)
int fileVersion = readBuffer.readInt(); int fileVersion = readBuffer.readInt();
if (fileVersion != SUPPORTED_FILE_VERSION) { if (fileVersion != FILE_VERSION_3 && fileVersion != FILE_VERSION_4) {
return new OpenResult("unsupported file version: " + fileVersion); return new OpenResult("unsupported file version: " + fileVersion);
} }
mapFileInfoBuilder.fileVersion = fileVersion; mapFileInfoBuilder.fileVersion = fileVersion;