From 5c011a2402d38ab87585a934af6b79640b9cda4e Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Mon, 23 Sep 2013 01:33:24 +0200 Subject: [PATCH] reduce points on-the-fly while reading from mapfile --- .../tiling/source/mapfile/MapDatabase.java | 397 +++++++++--------- 1 file changed, 201 insertions(+), 196 deletions(-) diff --git a/vtm/src/org/oscim/tiling/source/mapfile/MapDatabase.java b/vtm/src/org/oscim/tiling/source/mapfile/MapDatabase.java index 87a6851e..fb3ddf27 100644 --- a/vtm/src/org/oscim/tiling/source/mapfile/MapDatabase.java +++ b/vtm/src/org/oscim/tiling/source/mapfile/MapDatabase.java @@ -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 Specification */ 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;