reduce points on-the-fly while reading from mapfile

This commit is contained in:
Hannes Janetzek 2013-09-23 01:33:24 +02:00
parent 8a2060ca6e
commit 5c011a2402

View File

@ -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;