reduce points on-the-fly while reading from mapfile
This commit is contained in:
parent
8a2060ca6e
commit
5c011a2402
@ -18,8 +18,11 @@ package org.oscim.tiling.source.mapfile;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
import org.oscim.backend.Log;
|
||||
import org.oscim.core.GeometryBuffer;
|
||||
import org.oscim.core.GeometryBuffer.GeometryType;
|
||||
import org.oscim.core.MapElement;
|
||||
import org.oscim.core.MercatorProjection;
|
||||
import org.oscim.core.Tag;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.tiling.MapTile;
|
||||
@ -27,50 +30,34 @@ import org.oscim.tiling.source.ITileDataSink;
|
||||
import org.oscim.tiling.source.ITileDataSource;
|
||||
import org.oscim.tiling.source.mapfile.header.SubFileParameter;
|
||||
|
||||
import org.oscim.backend.Log;
|
||||
|
||||
/**
|
||||
* A class for reading binary map files.
|
||||
*
|
||||
*
|
||||
* @see <a
|
||||
* href="http://code.google.com/p/mapsforge/wiki/SpecificationBinaryMapFile">Specification</a>
|
||||
*/
|
||||
public class MapDatabase implements ITileDataSource {
|
||||
/**
|
||||
* Bitmask to extract the block offset from an index entry.
|
||||
*/
|
||||
/** Bitmask to extract the block offset from an index entry. */
|
||||
private static final long BITMASK_INDEX_OFFSET = 0x7FFFFFFFFFL;
|
||||
|
||||
/**
|
||||
* Bitmask to extract the water information from an index entry.
|
||||
*/
|
||||
/** Bitmask to extract the water information from an index entry. */
|
||||
private static final long BITMASK_INDEX_WATER = 0x8000000000L;
|
||||
|
||||
/**
|
||||
* Debug message prefix for the block signature.
|
||||
*/
|
||||
/** Debug message prefix for the block signature. */
|
||||
private static final String DEBUG_SIGNATURE_BLOCK = "block signature: ";
|
||||
|
||||
/**
|
||||
* Debug message prefix for the POI signature.
|
||||
*/
|
||||
/** Debug message prefix for the POI signature. */
|
||||
// private static final String DEBUG_SIGNATURE_POI = "POI signature: ";
|
||||
|
||||
/**
|
||||
* Debug message prefix for the way signature.
|
||||
*/
|
||||
/** Debug message prefix for the way signature. */
|
||||
private static final String DEBUG_SIGNATURE_WAY = "way signature: ";
|
||||
|
||||
/**
|
||||
* Error message for an invalid first way offset.
|
||||
*/
|
||||
/** Error message for an invalid first way offset. */
|
||||
private static final String INVALID_FIRST_WAY_OFFSET = "invalid first way offset: ";
|
||||
|
||||
private static final String TAG = MapDatabase.class.getName();
|
||||
|
||||
/**
|
||||
* Maximum way nodes sequence length which is considered as valid.
|
||||
*/
|
||||
/** Maximum way nodes sequence length which is considered as valid. */
|
||||
private static final int MAXIMUM_WAY_NODES_SEQUENCE_LENGTH = 8192;
|
||||
|
||||
/**
|
||||
@ -79,97 +66,60 @@ public class MapDatabase implements ITileDataSource {
|
||||
*/
|
||||
private static final int MAXIMUM_ZOOM_TABLE_OBJECTS = 65536;
|
||||
|
||||
/**
|
||||
* Bitmask for the optional POI feature "elevation".
|
||||
*/
|
||||
/** Bitmask for the optional POI feature "elevation". */
|
||||
private static final int POI_FEATURE_ELEVATION = 0x20;
|
||||
|
||||
/**
|
||||
* Bitmask for the optional POI feature "house number".
|
||||
*/
|
||||
/** Bitmask for the optional POI feature "house number". */
|
||||
private static final int POI_FEATURE_HOUSE_NUMBER = 0x40;
|
||||
|
||||
/**
|
||||
* Bitmask for the optional POI feature "name".
|
||||
*/
|
||||
/** Bitmask for the optional POI feature "name". */
|
||||
private static final int POI_FEATURE_NAME = 0x80;
|
||||
|
||||
/**
|
||||
* Bitmask for the POI layer.
|
||||
*/
|
||||
/** Bitmask for the POI layer. */
|
||||
private static final int POI_LAYER_BITMASK = 0xf0;
|
||||
|
||||
/**
|
||||
* Bit shift for calculating the POI layer.
|
||||
*/
|
||||
/** Bit shift for calculating the POI layer. */
|
||||
private static final int POI_LAYER_SHIFT = 4;
|
||||
|
||||
/**
|
||||
* Bitmask for the number of POI tags.
|
||||
*/
|
||||
/** Bitmask for the number of POI tags. */
|
||||
private static final int POI_NUMBER_OF_TAGS_BITMASK = 0x0f;
|
||||
|
||||
/**
|
||||
* Length of the debug signature at the beginning of each block.
|
||||
*/
|
||||
/** Length of the debug signature at the beginning of each block. */
|
||||
private static final byte SIGNATURE_LENGTH_BLOCK = 32;
|
||||
|
||||
/**
|
||||
* Length of the debug signature at the beginning of each POI.
|
||||
*/
|
||||
/** Length of the debug signature at the beginning of each POI. */
|
||||
private static final byte SIGNATURE_LENGTH_POI = 32;
|
||||
|
||||
/**
|
||||
* Length of the debug signature at the beginning of each way.
|
||||
*/
|
||||
/** Length of the debug signature at the beginning of each way. */
|
||||
private static final byte SIGNATURE_LENGTH_WAY = 32;
|
||||
|
||||
/**
|
||||
* Bitmask for the optional way data blocks byte.
|
||||
*/
|
||||
/** Bitmask for the optional way data blocks byte. */
|
||||
private static final int WAY_FEATURE_DATA_BLOCKS_BYTE = 0x08;
|
||||
|
||||
/**
|
||||
* Bitmask for the optional way double delta encoding.
|
||||
*/
|
||||
/** Bitmask for the optional way double delta encoding. */
|
||||
private static final int WAY_FEATURE_DOUBLE_DELTA_ENCODING = 0x04;
|
||||
|
||||
/**
|
||||
* Bitmask for the optional way feature "house number".
|
||||
*/
|
||||
/** Bitmask for the optional way feature "house number". */
|
||||
private static final int WAY_FEATURE_HOUSE_NUMBER = 0x40;
|
||||
|
||||
/**
|
||||
* Bitmask for the optional way feature "label position".
|
||||
*/
|
||||
/** Bitmask for the optional way feature "label position". */
|
||||
private static final int WAY_FEATURE_LABEL_POSITION = 0x10;
|
||||
|
||||
/**
|
||||
* Bitmask for the optional way feature "name".
|
||||
*/
|
||||
/** Bitmask for the optional way feature "name". */
|
||||
private static final int WAY_FEATURE_NAME = 0x80;
|
||||
|
||||
/**
|
||||
* Bitmask for the optional way feature "reference".
|
||||
*/
|
||||
/** Bitmask for the optional way feature "reference". */
|
||||
private static final int WAY_FEATURE_REF = 0x20;
|
||||
|
||||
/**
|
||||
* Bitmask for the way layer.
|
||||
*/
|
||||
/** Bitmask for the way layer. */
|
||||
private static final int WAY_LAYER_BITMASK = 0xf0;
|
||||
|
||||
/**
|
||||
* Bit shift for calculating the way layer.
|
||||
*/
|
||||
/** Bit shift for calculating the way layer. */
|
||||
private static final int WAY_LAYER_SHIFT = 4;
|
||||
|
||||
/**
|
||||
* Bitmask for the number of way tags.
|
||||
*/
|
||||
/** Bitmask for the number of way tags. */
|
||||
private static final int WAY_NUMBER_OF_TAGS_BITMASK = 0x0f;
|
||||
|
||||
|
||||
private long mFileSize;
|
||||
private boolean mDebugFile;
|
||||
private RandomAccessFile mInputFile;
|
||||
@ -188,6 +138,8 @@ public class MapDatabase implements ITileDataSource {
|
||||
|
||||
private final MapFileTileSource mTileSource;
|
||||
|
||||
//private int mReductionCnt;
|
||||
//private int mSkipPoly;
|
||||
|
||||
@Override
|
||||
public QueryResult executeQuery(MapTile tile, ITileDataSink mapDataSink) {
|
||||
@ -201,15 +153,38 @@ public class MapDatabase implements ITileDataSource {
|
||||
try {
|
||||
mTile = tile;
|
||||
|
||||
// size of tile in map coordinates;
|
||||
double size = 1.0 / (1 << tile.zoomLevel);
|
||||
|
||||
// simplification tolerance
|
||||
int pixel = (tile.zoomLevel > 11) ? 1 : 2;
|
||||
|
||||
int simplify = Tile.SIZE / pixel;
|
||||
|
||||
// translate screen pixel for tile to latitude and longitude
|
||||
// tolerance for point reduction before projection.
|
||||
minLat = (int) (Math.abs(MercatorProjection.toLatitude(tile.y + size)
|
||||
- MercatorProjection.toLatitude(tile.y)) * 1e6) / simplify;
|
||||
minLon = (int) (Math.abs(MercatorProjection.toLongitude(tile.x + size)
|
||||
- MercatorProjection.toLongitude(tile.x)) * 1e6) / simplify;
|
||||
|
||||
//mReductionCnt = 0;
|
||||
//mSkipPoly = 0;
|
||||
|
||||
//Log.d(TAG, "simplify by " + minLat + "/" + minLon);
|
||||
|
||||
QueryParameters queryParameters = new QueryParameters();
|
||||
queryParameters.queryZoomLevel = mTileSource.fileHeader
|
||||
.getQueryZoomLevel(tile.zoomLevel);
|
||||
queryParameters.queryZoomLevel =
|
||||
mTileSource.fileHeader.getQueryZoomLevel(tile.zoomLevel);
|
||||
|
||||
// get and check the sub-file for the query zoom level
|
||||
SubFileParameter subFileParameter = mTileSource.fileHeader
|
||||
.getSubFileParameter(queryParameters.queryZoomLevel);
|
||||
SubFileParameter subFileParameter =
|
||||
mTileSource.fileHeader.getSubFileParameter(queryParameters.queryZoomLevel);
|
||||
|
||||
if (subFileParameter == null) {
|
||||
Log.w(TAG, "no sub-file for zoom level: "
|
||||
+ queryParameters.queryZoomLevel);
|
||||
+ queryParameters.queryZoomLevel);
|
||||
|
||||
return QueryResult.FAILED;
|
||||
}
|
||||
|
||||
@ -220,24 +195,27 @@ public class MapDatabase implements ITileDataSource {
|
||||
Log.e(TAG, e.getMessage());
|
||||
return QueryResult.FAILED;
|
||||
}
|
||||
|
||||
//Log.d(TAG, "reduced points " + mReductionCnt + " / polys " + mSkipPoly);
|
||||
|
||||
return QueryResult.SUCCESS;
|
||||
}
|
||||
|
||||
public MapDatabase(MapFileTileSource tileSource) throws IOException {
|
||||
mTileSource = tileSource;
|
||||
try {
|
||||
// open the file in read only mode
|
||||
mInputFile = new RandomAccessFile(tileSource.mapFile, "r");
|
||||
mFileSize = mInputFile.length();
|
||||
mReadBuffer = new ReadBuffer(mInputFile);
|
||||
try {
|
||||
// open the file in read only mode
|
||||
mInputFile = new RandomAccessFile(tileSource.mapFile, "r");
|
||||
mFileSize = mInputFile.length();
|
||||
mReadBuffer = new ReadBuffer(mInputFile);
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
// make sure that the file is closed
|
||||
destroy();
|
||||
throw new IOException();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
// make sure that the file is closed
|
||||
destroy();
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
@ -251,7 +229,6 @@ public class MapDatabase implements ITileDataSource {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -267,7 +244,7 @@ public class MapDatabase implements ITileDataSource {
|
||||
/**
|
||||
* Processes a single block and executes the callback functions on all map
|
||||
* elements.
|
||||
*
|
||||
*
|
||||
* @param queryParameters
|
||||
* the parameters of the current query.
|
||||
* @param subFileParameter
|
||||
@ -276,8 +253,8 @@ public class MapDatabase implements ITileDataSource {
|
||||
* the callback which handles the extracted map elements.
|
||||
*/
|
||||
private void processBlock(QueryParameters queryParameters,
|
||||
SubFileParameter subFileParameter,
|
||||
ITileDataSink mapDataSink) {
|
||||
SubFileParameter subFileParameter,
|
||||
ITileDataSink mapDataSink) {
|
||||
if (!processBlockSignature()) {
|
||||
return;
|
||||
}
|
||||
@ -332,8 +309,8 @@ public class MapDatabase implements ITileDataSource {
|
||||
}
|
||||
|
||||
private void processBlocks(ITileDataSink mapDataSink,
|
||||
QueryParameters queryParameters,
|
||||
SubFileParameter subFileParameter) throws IOException {
|
||||
QueryParameters queryParameters,
|
||||
SubFileParameter subFileParameter) throws IOException {
|
||||
boolean queryIsWater = true;
|
||||
// boolean queryReadWaterInfo = false;
|
||||
|
||||
@ -346,8 +323,8 @@ public class MapDatabase implements ITileDataSource {
|
||||
long blockNumber = row * subFileParameter.blocksWidth + column;
|
||||
|
||||
// get the current index entry
|
||||
long currentBlockIndexEntry = mTileSource.databaseIndexCache.getIndexEntry(
|
||||
subFileParameter, blockNumber);
|
||||
long currentBlockIndexEntry =
|
||||
mTileSource.databaseIndexCache.getIndexEntry(subFileParameter, blockNumber);
|
||||
|
||||
// check if the current query would still return a water tile
|
||||
if (queryIsWater) {
|
||||
@ -360,7 +337,7 @@ public class MapDatabase implements ITileDataSource {
|
||||
// get and check the current block pointer
|
||||
long currentBlockPointer = currentBlockIndexEntry & BITMASK_INDEX_OFFSET;
|
||||
if (currentBlockPointer < 1
|
||||
|| currentBlockPointer > subFileParameter.subFileSize) {
|
||||
|| currentBlockPointer > subFileParameter.subFileSize) {
|
||||
Log.w(TAG, "invalid current block pointer: " + currentBlockPointer);
|
||||
Log.w(TAG, "subFileSize: " + subFileParameter.subFileSize);
|
||||
return;
|
||||
@ -373,11 +350,12 @@ public class MapDatabase implements ITileDataSource {
|
||||
nextBlockPointer = subFileParameter.subFileSize;
|
||||
} else {
|
||||
// get and check the next block pointer
|
||||
nextBlockPointer = mTileSource.databaseIndexCache.getIndexEntry(
|
||||
subFileParameter, blockNumber + 1)
|
||||
& BITMASK_INDEX_OFFSET;
|
||||
nextBlockPointer =
|
||||
mTileSource.databaseIndexCache.getIndexEntry(subFileParameter,
|
||||
blockNumber + 1)
|
||||
& BITMASK_INDEX_OFFSET;
|
||||
if (nextBlockPointer < 1
|
||||
|| nextBlockPointer > subFileParameter.subFileSize) {
|
||||
|| nextBlockPointer > subFileParameter.subFileSize) {
|
||||
Log.w(TAG, "invalid next block pointer: " + nextBlockPointer);
|
||||
Log.w(TAG, "sub-file size: " + subFileParameter.subFileSize);
|
||||
return;
|
||||
@ -388,7 +366,7 @@ public class MapDatabase implements ITileDataSource {
|
||||
int currentBlockSize = (int) (nextBlockPointer - currentBlockPointer);
|
||||
if (currentBlockSize < 0) {
|
||||
Log.w(TAG, "current block size must not be negative: "
|
||||
+ currentBlockSize);
|
||||
+ currentBlockSize);
|
||||
return;
|
||||
} else if (currentBlockSize == 0) {
|
||||
// the current block is empty, continue with the next block
|
||||
@ -400,7 +378,7 @@ public class MapDatabase implements ITileDataSource {
|
||||
continue;
|
||||
} else if (currentBlockPointer + currentBlockSize > mFileSize) {
|
||||
Log.w(TAG, "current block larger than file size: "
|
||||
+ currentBlockSize);
|
||||
+ currentBlockSize);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -415,14 +393,15 @@ public class MapDatabase implements ITileDataSource {
|
||||
}
|
||||
|
||||
// calculate the top-left coordinates of the underlying tile
|
||||
double tileLatitudeDeg = Projection.tileYToLatitude(
|
||||
subFileParameter.boundaryTileTop + row,
|
||||
subFileParameter.baseZoomLevel);
|
||||
double tileLongitudeDeg = Projection.tileXToLongitude(
|
||||
subFileParameter.boundaryTileLeft
|
||||
+ column, subFileParameter.baseZoomLevel);
|
||||
mTileLatitude = (int) (tileLatitudeDeg * 1000000);
|
||||
mTileLongitude = (int) (tileLongitudeDeg * 1000000);
|
||||
double tileLatitudeDeg =
|
||||
Projection.tileYToLatitude(subFileParameter.boundaryTileTop + row,
|
||||
subFileParameter.baseZoomLevel);
|
||||
double tileLongitudeDeg =
|
||||
Projection.tileXToLongitude(subFileParameter.boundaryTileLeft + column,
|
||||
subFileParameter.baseZoomLevel);
|
||||
|
||||
mTileLatitude = (int) (tileLatitudeDeg * 1E6);
|
||||
mTileLongitude = (int) (tileLongitudeDeg * 1E6);
|
||||
|
||||
processBlock(queryParameters, subFileParameter, mapDataSink);
|
||||
}
|
||||
@ -438,12 +417,11 @@ public class MapDatabase implements ITileDataSource {
|
||||
// mWayNodePosition += 8;
|
||||
// mapDatabaseCallback.renderWaterBackground(tags, wayDataContainer);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the block signature, if present.
|
||||
*
|
||||
*
|
||||
* @return true if the block signature could be processed successfully,
|
||||
* false otherwise.
|
||||
*/
|
||||
@ -461,7 +439,7 @@ public class MapDatabase implements ITileDataSource {
|
||||
|
||||
/**
|
||||
* Processes the given number of POIs.
|
||||
*
|
||||
*
|
||||
* @param mapDataSink
|
||||
* the callback which handles the extracted POIs.
|
||||
* @param numberOfPois
|
||||
@ -543,15 +521,16 @@ public class MapDatabase implements ITileDataSource {
|
||||
// Integer.toString(mReadBuffer.readSignedInt())));
|
||||
}
|
||||
|
||||
longitude = (int) (longitude / divx - dx);
|
||||
float lon = (float) (longitude / divx - dx);
|
||||
|
||||
double sinLat = Math.sin(latitude * PI180);
|
||||
latitude = (int) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
|
||||
float lat = Tile.SIZE
|
||||
- (float) ((Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy));
|
||||
|
||||
mElem.clear();
|
||||
mElem.startPoints();
|
||||
mElem.addPoint(longitude, latitude);
|
||||
mElem.type = GeometryType.POINT;
|
||||
mElem.setLayer(layer);
|
||||
mElem.startPoints();
|
||||
mElem.addPoint(lon, lat);
|
||||
|
||||
mapDataSink.process(mElem);
|
||||
}
|
||||
@ -572,7 +551,7 @@ public class MapDatabase implements ITileDataSource {
|
||||
if (wayLengths.length > numBlocks)
|
||||
wayLengths[numBlocks] = -1;
|
||||
|
||||
mElem.pointPos = 0;
|
||||
//mElem.pointPos = 0;
|
||||
|
||||
// read the way coordinate blocks
|
||||
for (int coordinateBlock = 0; coordinateBlock < numBlocks; ++coordinateBlock) {
|
||||
@ -605,44 +584,53 @@ public class MapDatabase implements ITileDataSource {
|
||||
mReadBuffer.readSignedInt(buffer, length);
|
||||
|
||||
float[] outBuffer = mElem.ensurePointSize(mElem.pointPos + length, true);
|
||||
int pointPos = mElem.pointPos;
|
||||
int outPos = mElem.pointPos;
|
||||
int lat, lon;
|
||||
|
||||
// get the first way node latitude offset (VBE-S)
|
||||
int wayNodeLatitude = mTileLatitude + buffer[0];
|
||||
// get the first way node latitude offset
|
||||
int firstLat = lat = mTileLatitude + buffer[0];
|
||||
|
||||
// get the first way node longitude offset (VBE-S)
|
||||
int wayNodeLongitude = mTileLongitude + buffer[1];
|
||||
// get the first way node longitude offset
|
||||
int firstLon = lon = mTileLongitude + buffer[1];
|
||||
|
||||
// store the first way node
|
||||
outBuffer[pointPos++] = wayNodeLongitude;
|
||||
outBuffer[pointPos++] = wayNodeLatitude;
|
||||
outBuffer[outPos++] = lon;
|
||||
outBuffer[outPos++] = lat;
|
||||
int cnt = 2;
|
||||
|
||||
int singleDeltaLatitude = 0;
|
||||
int singleDeltaLongitude = 0;
|
||||
|
||||
int cnt = 2, nLon, nLat, dLat, dLon;
|
||||
int deltaLat = 0;
|
||||
int deltaLon = 0;
|
||||
|
||||
for (int pos = 2; pos < length; pos += 2) {
|
||||
deltaLat = buffer[pos] + deltaLat;
|
||||
lat += deltaLat;
|
||||
|
||||
singleDeltaLatitude = buffer[pos] + singleDeltaLatitude;
|
||||
nLat = wayNodeLatitude + singleDeltaLatitude;
|
||||
dLat = nLat - wayNodeLatitude;
|
||||
wayNodeLatitude = nLat;
|
||||
deltaLon = buffer[pos + 1] + deltaLon;
|
||||
lon += deltaLon;
|
||||
|
||||
singleDeltaLongitude = buffer[pos + 1] + singleDeltaLongitude;
|
||||
nLon = wayNodeLongitude + singleDeltaLongitude;
|
||||
dLon = nLon - wayNodeLongitude;
|
||||
wayNodeLongitude = nLon;
|
||||
if (pos == length - 2) {
|
||||
boolean line = (lon != firstLon && lat != firstLat);
|
||||
// this also removes closed ways that are not polygon,
|
||||
// but how do we know?
|
||||
if (line) {
|
||||
outBuffer[outPos++] = lon;
|
||||
outBuffer[outPos++] = lat;
|
||||
cnt += 2;
|
||||
}
|
||||
|
||||
if (dLon > minLon || dLon < -minLon || dLat > minLat || dLat < -minLat
|
||||
|| (pos == length - 2)) {
|
||||
outBuffer[pointPos++] = nLon;
|
||||
outBuffer[pointPos++] = nLat;
|
||||
if (mElem.type == GeometryType.NONE) {
|
||||
mElem.type = line ? GeometryType.LINE : GeometryType.POLY;
|
||||
}
|
||||
|
||||
} else if (deltaLon > minLon || deltaLon < -minLon
|
||||
|| deltaLat > minLat || deltaLat < -minLat) {
|
||||
outBuffer[outPos++] = lon;
|
||||
outBuffer[outPos++] = lat;
|
||||
cnt += 2;
|
||||
}
|
||||
}
|
||||
|
||||
mElem.pointPos = pointPos;
|
||||
//mReductionCnt += length - cnt;
|
||||
mElem.pointPos = outPos;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
@ -652,39 +640,49 @@ public class MapDatabase implements ITileDataSource {
|
||||
mReadBuffer.readSignedInt(buffer, length);
|
||||
|
||||
float[] outBuffer = mElem.ensurePointSize(mElem.pointPos + length, true);
|
||||
int pointPos = mElem.pointPos;
|
||||
int outPos = mElem.pointPos;
|
||||
int lat, lon;
|
||||
|
||||
// get the first way node latitude single-delta offset (VBE-S)
|
||||
int wayNodeLatitude = mTileLatitude + buffer[0];
|
||||
// get the first way node latitude single-delta offset
|
||||
int firstLat = lat = mTileLatitude + buffer[0];
|
||||
|
||||
// get the first way node longitude single-delta offset (VBE-S)
|
||||
int wayNodeLongitude = mTileLongitude + buffer[1];
|
||||
// get the first way node longitude single-delta offset
|
||||
int firstLon = lon = mTileLongitude + buffer[1];
|
||||
|
||||
// store the first way node
|
||||
outBuffer[pointPos++] = wayNodeLongitude;
|
||||
outBuffer[pointPos++] = wayNodeLatitude;
|
||||
|
||||
int cnt = 2, nLon, nLat, dLat, dLon;
|
||||
outBuffer[outPos++] = lon;
|
||||
outBuffer[outPos++] = lat;
|
||||
int cnt = 2;
|
||||
|
||||
for (int pos = 2; pos < length; pos += 2) {
|
||||
int deltaLat = buffer[pos];
|
||||
lat += deltaLat;
|
||||
|
||||
nLat = wayNodeLatitude + buffer[pos];
|
||||
dLat = nLat - wayNodeLatitude;
|
||||
wayNodeLatitude = nLat;
|
||||
int deltaLon = buffer[pos + 1];
|
||||
lon += deltaLon;
|
||||
|
||||
nLon = wayNodeLongitude + buffer[pos + 1];
|
||||
dLon = nLon - wayNodeLongitude;
|
||||
wayNodeLongitude = nLon;
|
||||
if (pos == length - 2) {
|
||||
boolean line = (lon != firstLon && lat != firstLat);
|
||||
|
||||
if (dLon > minLon || dLon < -minLon || dLat > minLat || dLat < -minLat
|
||||
|| (pos == length - 2)) {
|
||||
outBuffer[pointPos++] = nLon;
|
||||
outBuffer[pointPos++] = nLat;
|
||||
if (line) {
|
||||
outBuffer[outPos++] = lon;
|
||||
outBuffer[outPos++] = lat;
|
||||
cnt += 2;
|
||||
}
|
||||
|
||||
if (mElem.type == GeometryType.NONE)
|
||||
mElem.type = line ? GeometryType.LINE : GeometryType.POLY;
|
||||
|
||||
} else if (deltaLon > minLon || deltaLon < -minLon
|
||||
|| deltaLat > minLat || deltaLat < -minLat) {
|
||||
outBuffer[outPos++] = lon;
|
||||
outBuffer[outPos++] = lat;
|
||||
cnt += 2;
|
||||
}
|
||||
}
|
||||
|
||||
mElem.pointPos = pointPos;
|
||||
//mReductionCnt += length - cnt;
|
||||
mElem.pointPos = outPos;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
@ -692,7 +690,7 @@ public class MapDatabase implements ITileDataSource {
|
||||
|
||||
/**
|
||||
* Processes the given number of ways.
|
||||
*
|
||||
*
|
||||
* @param queryParameters
|
||||
* the parameters of the current query.
|
||||
* @param mapDataSink
|
||||
@ -703,8 +701,8 @@ public class MapDatabase implements ITileDataSource {
|
||||
* otherwise.
|
||||
*/
|
||||
private boolean processWays(QueryParameters queryParameters,
|
||||
ITileDataSink mapDataSink,
|
||||
int numberOfWays) {
|
||||
ITileDataSink mapDataSink,
|
||||
int numberOfWays) {
|
||||
|
||||
Tag[] wayTags = mTileSource.fileInfo.wayTags;
|
||||
int numTags = 0;
|
||||
@ -734,7 +732,7 @@ public class MapDatabase implements ITileDataSource {
|
||||
|
||||
if (queryParameters.useTileBitmask) {
|
||||
elementCounter = mReadBuffer.skipWays(queryParameters.queryTileBitmask,
|
||||
elementCounter);
|
||||
elementCounter);
|
||||
|
||||
if (elementCounter == 0)
|
||||
return true;
|
||||
@ -746,7 +744,8 @@ public class MapDatabase implements ITileDataSource {
|
||||
int pos = mReadBuffer.getBufferPosition();
|
||||
mReadBuffer.setBufferPosition(mReadBuffer.lastTagPosition);
|
||||
|
||||
byte numberOfTags = (byte) (mReadBuffer.readByte() & WAY_NUMBER_OF_TAGS_BITMASK);
|
||||
byte numberOfTags =
|
||||
(byte) (mReadBuffer.readByte() & WAY_NUMBER_OF_TAGS_BITMASK);
|
||||
if (!mReadBuffer.readTags(mElem.tags, wayTags, numberOfTags))
|
||||
return false;
|
||||
|
||||
@ -777,7 +776,7 @@ public class MapDatabase implements ITileDataSource {
|
||||
// bit 5-8 represent the number of tag IDs
|
||||
byte numberOfTags = (byte) (specialByte & WAY_NUMBER_OF_TAGS_BITMASK);
|
||||
|
||||
if (numberOfTags != 0){
|
||||
if (numberOfTags != 0) {
|
||||
|
||||
if (!mReadBuffer.readTags(mElem.tags, wayTags, numberOfTags))
|
||||
return false;
|
||||
@ -789,7 +788,8 @@ public class MapDatabase implements ITileDataSource {
|
||||
byte featureByte = mReadBuffer.readByte();
|
||||
|
||||
// bit 1-6 enable optional features
|
||||
boolean featureWayDoubleDeltaEncoding = (featureByte & WAY_FEATURE_DOUBLE_DELTA_ENCODING) != 0;
|
||||
boolean featureWayDoubleDeltaEncoding =
|
||||
(featureByte & WAY_FEATURE_DOUBLE_DELTA_ENCODING) != 0;
|
||||
|
||||
boolean hasName = (featureByte & WAY_FEATURE_NAME) != 0;
|
||||
boolean hasHouseNr = (featureByte & WAY_FEATURE_HOUSE_NUMBER) != 0;
|
||||
@ -843,21 +843,20 @@ public class MapDatabase implements ITileDataSource {
|
||||
wayDataBlocks = 1;
|
||||
}
|
||||
|
||||
for (int wayDataBlock = 0; wayDataBlock < wayDataBlocks; ++wayDataBlock) {
|
||||
for (int wayDataBlock = 0; wayDataBlock < wayDataBlocks; wayDataBlock++) {
|
||||
mElem.clear();
|
||||
|
||||
if (!processWayDataBlock(featureWayDoubleDeltaEncoding))
|
||||
return false;
|
||||
|
||||
// wayDataContainer.textPos = textPos;
|
||||
int l = mElem.index[0];
|
||||
if (mElem.isPoly() && mElem.index[0] < 6) {
|
||||
//mSkipPoly++;
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean closed = mElem.points[0] == mElem.points[l - 2]
|
||||
&& mElem.points[1] == mElem.points[l - 1];
|
||||
projectToTile(mElem);
|
||||
|
||||
projectToTile(mElem.points, mElem.index);
|
||||
|
||||
mElem.type = closed ? GeometryType.POLY : GeometryType.LINE;
|
||||
mElem.setLayer(layer);
|
||||
|
||||
mapDataSink.process(mElem);
|
||||
}
|
||||
}
|
||||
@ -889,17 +888,17 @@ public class MapDatabase implements ITileDataSource {
|
||||
cumulatedNumberOfWays += mReadBuffer.readUnsignedInt();
|
||||
|
||||
if (cumulatedNumberOfPois < 0
|
||||
|| cumulatedNumberOfPois > MAXIMUM_ZOOM_TABLE_OBJECTS) {
|
||||
|| cumulatedNumberOfPois > MAXIMUM_ZOOM_TABLE_OBJECTS) {
|
||||
Log.w(TAG, "invalid cumulated number of POIs in row " + row + ' '
|
||||
+ cumulatedNumberOfPois);
|
||||
+ cumulatedNumberOfPois);
|
||||
if (mDebugFile) {
|
||||
Log.w(TAG, DEBUG_SIGNATURE_BLOCK + mSignatureBlock);
|
||||
}
|
||||
return null;
|
||||
} else if (cumulatedNumberOfWays < 0
|
||||
|| cumulatedNumberOfWays > MAXIMUM_ZOOM_TABLE_OBJECTS) {
|
||||
|| cumulatedNumberOfWays > MAXIMUM_ZOOM_TABLE_OBJECTS) {
|
||||
Log.w(TAG, "invalid cumulated number of ways in row " + row + ' '
|
||||
+ cumulatedNumberOfWays);
|
||||
+ cumulatedNumberOfWays);
|
||||
if (mTileSource.fileInfo.debugFile) {
|
||||
Log.w(TAG, DEBUG_SIGNATURE_BLOCK + mSignatureBlock);
|
||||
}
|
||||
@ -916,7 +915,10 @@ public class MapDatabase implements ITileDataSource {
|
||||
private static final double PI180 = (Math.PI / 180) / 1000000.0;
|
||||
private static final double PIx4 = Math.PI * 4;
|
||||
|
||||
private boolean projectToTile(float[] coords, short[] indices) {
|
||||
private boolean projectToTile(GeometryBuffer geom) {
|
||||
|
||||
float[] coords = geom.points;
|
||||
short[] indices = geom.index;
|
||||
|
||||
long x = mTile.tileX * Tile.SIZE;
|
||||
long y = mTile.tileY * Tile.SIZE + Tile.SIZE;
|
||||
@ -948,15 +950,18 @@ public class MapDatabase implements ITileDataSource {
|
||||
|
||||
if (cnt != 0) {
|
||||
// drop small distance intermediate nodes
|
||||
if (lat == prevLat && lon == prevLon)
|
||||
if (lat == prevLat && lon == prevLon) {
|
||||
//Log.d(TAG, "drop zero delta ");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
coords[outPos++] = prevLon = lon;
|
||||
coords[outPos++] = prevLat = lat;
|
||||
|
||||
cnt += 2;
|
||||
}
|
||||
if (coords[first] == coords[outPos - 2] && coords[first + 1] == coords[outPos - 1]) {
|
||||
|
||||
if (coords[first] == prevLon && coords[first + 1] == prevLat) {
|
||||
//Log.d(TAG, "drop closed");
|
||||
indices[i] = (short) (cnt - 2);
|
||||
outPos -= 2;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user