- adding MapDatabase backend for our TileStache provider
- fixing some renering bugs on nexus phone and some refactoring and cleanup
This commit is contained in:
@@ -62,6 +62,8 @@ public interface IMapDatabase {
|
||||
*/
|
||||
public abstract FileOpenResult openFile(File mapFile);
|
||||
|
||||
public abstract String getMapProjection();
|
||||
|
||||
/**
|
||||
* @param position
|
||||
* ....
|
||||
@@ -69,4 +71,4 @@ public interface IMapDatabase {
|
||||
*/
|
||||
public abstract String readString(int position);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,13 +31,14 @@ import org.mapsforge.database.MapFileInfo;
|
||||
*/
|
||||
public class MapDatabase implements IMapDatabase {
|
||||
|
||||
private final static String PROJECTION = "Mercator";
|
||||
private float[] mCoords = new float[20];
|
||||
private int[] mIndex = new int[1];
|
||||
private int[] mIndex = new int[2];
|
||||
// private Tag[] mTags = { new Tag("boundary", "administrative"), new Tag("admin_level", "2") };
|
||||
private Tag[] mTags = { new Tag("building", "yes") };
|
||||
private Tag[] mTags = { new Tag("natural", "water") };
|
||||
private final MapFileInfo mMapInfo =
|
||||
new MapFileInfo(new BoundingBox(-180, -90, 180, 90),
|
||||
new Byte((byte) 0), null, "Mercator", 0, 0, 0, "de", "yo!", "by me");
|
||||
new Byte((byte) 0), null, PROJECTION, 0, 0, 0, "de", "yo!", "by me");
|
||||
|
||||
private boolean mOpenFile = false;
|
||||
|
||||
@@ -95,10 +96,10 @@ public class MapDatabase implements IMapDatabase {
|
||||
//
|
||||
// mIndex[0] = 10;
|
||||
|
||||
lon1 = (float) MercatorProjection.pixelXToLongitude(cx - 80, tile.zoomLevel) * 1000000;
|
||||
lon2 = (float) MercatorProjection.pixelXToLongitude(cx + 80, tile.zoomLevel) * 1000000;
|
||||
lat1 = (float) MercatorProjection.pixelYToLatitude(cy - 80, tile.zoomLevel) * 1000000;
|
||||
lat2 = (float) MercatorProjection.pixelYToLatitude(cy + 80, tile.zoomLevel) * 1000000;
|
||||
lon1 = (float) MercatorProjection.pixelXToLongitude(cx - 139, tile.zoomLevel) * 1000000;
|
||||
lon2 = (float) MercatorProjection.pixelXToLongitude(cx + 139, tile.zoomLevel) * 1000000;
|
||||
lat1 = (float) MercatorProjection.pixelYToLatitude(cy - 139, tile.zoomLevel) * 1000000;
|
||||
lat2 = (float) MercatorProjection.pixelYToLatitude(cy + 139, tile.zoomLevel) * 1000000;
|
||||
|
||||
mCoords[0] = lon1;
|
||||
mCoords[1] = lat1;
|
||||
@@ -117,9 +118,35 @@ public class MapDatabase implements IMapDatabase {
|
||||
|
||||
mIndex[0] = 10;
|
||||
|
||||
lon1 = (float) MercatorProjection.pixelXToLongitude(cx - 119, tile.zoomLevel) * 1000000;
|
||||
lon2 = (float) MercatorProjection.pixelXToLongitude(cx + 119, tile.zoomLevel) * 1000000;
|
||||
lat1 = (float) MercatorProjection.pixelYToLatitude(cy - 119, tile.zoomLevel) * 1000000;
|
||||
lat2 = (float) MercatorProjection.pixelYToLatitude(cy + 119, tile.zoomLevel) * 1000000;
|
||||
|
||||
mCoords[10] = lon1;
|
||||
mCoords[11] = lat1;
|
||||
|
||||
mCoords[12] = lon2;
|
||||
mCoords[13] = lat1;
|
||||
|
||||
mCoords[14] = lon2;
|
||||
mCoords[15] = lat2;
|
||||
|
||||
mCoords[16] = lon1;
|
||||
mCoords[17] = lat2;
|
||||
|
||||
mCoords[18] = lon1;
|
||||
mCoords[19] = lat1;
|
||||
|
||||
mIndex[1] = 10;
|
||||
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, mIndex, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMapProjection() {
|
||||
return PROJECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapFileInfo getMapFileInfo() {
|
||||
return mMapInfo;
|
||||
|
||||
@@ -177,11 +177,13 @@ public class MapDatabase implements IMapDatabase {
|
||||
*/
|
||||
private static final int WAY_NUMBER_OF_TAGS_BITMASK = 0x0f;
|
||||
|
||||
private IndexCache mDatabaseIndexCache;
|
||||
private static IndexCache sDatabaseIndexCache;
|
||||
private static MapFileHeader sMapFileHeader;
|
||||
private static int instances = 0;
|
||||
|
||||
private long mFileSize;
|
||||
private boolean mDebugFile;
|
||||
private RandomAccessFile mInputFile;
|
||||
private MapFileHeader mMapFileHeader;
|
||||
private ReadBuffer mReadBuffer;
|
||||
private String mSignatureBlock;
|
||||
private String mSignaturePoi;
|
||||
@@ -193,31 +195,6 @@ public class MapDatabase implements IMapDatabase {
|
||||
private float[] mWayNodes = new float[100000];
|
||||
private int mWayNodePosition;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.mapsforge.map.reader.IMapDatabase#closeFile()
|
||||
*/
|
||||
@Override
|
||||
public void closeFile() {
|
||||
try {
|
||||
mMapFileHeader = null;
|
||||
|
||||
if (mDatabaseIndexCache != null) {
|
||||
mDatabaseIndexCache.destroy();
|
||||
mDatabaseIndexCache = null;
|
||||
}
|
||||
|
||||
if (mInputFile != null) {
|
||||
mInputFile.close();
|
||||
mInputFile = null;
|
||||
}
|
||||
|
||||
mReadBuffer = null;
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.SEVERE, null, e);
|
||||
}
|
||||
}
|
||||
|
||||
private int minLat, minLon;
|
||||
|
||||
/*
|
||||
@@ -227,7 +204,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
*/
|
||||
@Override
|
||||
public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
|
||||
if (mMapFileHeader == null)
|
||||
if (sMapFileHeader == null)
|
||||
return;
|
||||
|
||||
if (mIntBuffer == null)
|
||||
@@ -235,29 +212,13 @@ public class MapDatabase implements IMapDatabase {
|
||||
|
||||
mWayNodePosition = 0;
|
||||
|
||||
// if (tile.zoomLevel < 10) {
|
||||
// // reduce small nodes with distance smaller min pixel
|
||||
// int min = 1;
|
||||
// long cx = tile.getPixelX() + (Tile.TILE_SIZE >> 1);
|
||||
// long cy = tile.getPixelY() + (Tile.TILE_SIZE >> 1);
|
||||
// double l1 = MercatorProjection.pixelXToLongitude(cx, tile.zoomLevel);
|
||||
// double l2 = MercatorProjection.pixelXToLongitude(cx + min, tile.zoomLevel);
|
||||
// minLon = (int) Math.abs((l1 * 1000000.0) - (l2 * 1000000.0));
|
||||
// l1 = MercatorProjection.pixelYToLatitude(cy, tile.zoomLevel);
|
||||
// l2 = MercatorProjection.pixelYToLatitude(cy + min, tile.zoomLevel);
|
||||
// minLat = (int) Math.abs((l1 * 1000000.0) - (l2 * 1000000.0));
|
||||
// } else {
|
||||
minLat = 0;
|
||||
minLon = 0;
|
||||
// }
|
||||
|
||||
try {
|
||||
prepareExecution();
|
||||
// prepareExecution();
|
||||
QueryParameters queryParameters = new QueryParameters();
|
||||
queryParameters.queryZoomLevel = mMapFileHeader
|
||||
queryParameters.queryZoomLevel = sMapFileHeader
|
||||
.getQueryZoomLevel(tile.zoomLevel);
|
||||
// get and check the sub-file for the query zoom level
|
||||
SubFileParameter subFileParameter = mMapFileHeader
|
||||
SubFileParameter subFileParameter = sMapFileHeader
|
||||
.getSubFileParameter(queryParameters.queryZoomLevel);
|
||||
if (subFileParameter == null) {
|
||||
LOG.warning("no sub-file for zoom level: "
|
||||
@@ -279,10 +240,15 @@ public class MapDatabase implements IMapDatabase {
|
||||
*/
|
||||
@Override
|
||||
public MapFileInfo getMapFileInfo() {
|
||||
if (mMapFileHeader == null) {
|
||||
if (sMapFileHeader == null) {
|
||||
throw new IllegalStateException("no map file is currently opened");
|
||||
}
|
||||
return mMapFileHeader.getMapFileInfo();
|
||||
return sMapFileHeader.getMapFileInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMapProjection() {
|
||||
return getMapFileInfo().projectionName;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -300,6 +266,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
*/
|
||||
@Override
|
||||
public FileOpenResult openFile(File mapFile) {
|
||||
|
||||
try {
|
||||
if (mapFile == null) {
|
||||
// throw new IllegalArgumentException("mapFile must not be null");
|
||||
@@ -323,14 +290,23 @@ public class MapDatabase implements IMapDatabase {
|
||||
mFileSize = mInputFile.length();
|
||||
mReadBuffer = new ReadBuffer(mInputFile);
|
||||
|
||||
mMapFileHeader = new MapFileHeader();
|
||||
FileOpenResult fileOpenResult = mMapFileHeader.readHeader(mReadBuffer,
|
||||
if (instances > 0) {
|
||||
instances++;
|
||||
return FileOpenResult.SUCCESS;
|
||||
}
|
||||
|
||||
sMapFileHeader = new MapFileHeader();
|
||||
FileOpenResult fileOpenResult = sMapFileHeader.readHeader(mReadBuffer,
|
||||
mFileSize);
|
||||
if (!fileOpenResult.isSuccess()) {
|
||||
closeFile();
|
||||
return fileOpenResult;
|
||||
}
|
||||
|
||||
prepareExecution();
|
||||
|
||||
instances++;
|
||||
|
||||
return FileOpenResult.SUCCESS;
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.SEVERE, null, e);
|
||||
@@ -340,6 +316,37 @@ public class MapDatabase implements IMapDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.mapsforge.map.reader.IMapDatabase#closeFile()
|
||||
*/
|
||||
@Override
|
||||
public void closeFile() {
|
||||
instances--;
|
||||
if (instances > 0) {
|
||||
mReadBuffer = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
sMapFileHeader = null;
|
||||
|
||||
if (sDatabaseIndexCache != null) {
|
||||
sDatabaseIndexCache.destroy();
|
||||
sDatabaseIndexCache = null;
|
||||
}
|
||||
|
||||
if (mInputFile != null) {
|
||||
mInputFile.close();
|
||||
mInputFile = null;
|
||||
}
|
||||
|
||||
mReadBuffer = null;
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.SEVERE, null, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the debug signatures of the current way and block.
|
||||
*/
|
||||
@@ -351,8 +358,8 @@ public class MapDatabase implements IMapDatabase {
|
||||
}
|
||||
|
||||
private void prepareExecution() {
|
||||
if (mDatabaseIndexCache == null) {
|
||||
mDatabaseIndexCache = new IndexCache(mInputFile, INDEX_CACHE_SIZE);
|
||||
if (sDatabaseIndexCache == null) {
|
||||
sDatabaseIndexCache = new IndexCache(mInputFile, INDEX_CACHE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -436,7 +443,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
long blockNumber = row * subFileParameter.blocksWidth + column;
|
||||
|
||||
// get the current index entry
|
||||
long currentBlockIndexEntry = mDatabaseIndexCache.getIndexEntry(
|
||||
long currentBlockIndexEntry = sDatabaseIndexCache.getIndexEntry(
|
||||
subFileParameter, blockNumber);
|
||||
|
||||
// check if the current query would still return a water tile
|
||||
@@ -462,7 +469,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
nextBlockPointer = subFileParameter.subFileSize;
|
||||
} else {
|
||||
// get and check the next block pointer
|
||||
nextBlockPointer = mDatabaseIndexCache.getIndexEntry(
|
||||
nextBlockPointer = sDatabaseIndexCache.getIndexEntry(
|
||||
subFileParameter, blockNumber + 1)
|
||||
& BITMASK_INDEX_OFFSET;
|
||||
if (nextBlockPointer < 1
|
||||
@@ -559,7 +566,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
* @return true if the POIs could be processed successfully, false otherwise.
|
||||
*/
|
||||
private boolean processPOIs(IMapDatabaseCallback mapDatabaseCallback, int numberOfPois) {
|
||||
Tag[] poiTags = mMapFileHeader.getMapFileInfo().poiTags;
|
||||
Tag[] poiTags = sMapFileHeader.getMapFileInfo().poiTags;
|
||||
Tag[] tags = null;
|
||||
|
||||
for (int elementCounter = numberOfPois; elementCounter != 0; --elementCounter) {
|
||||
@@ -778,7 +785,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
int numberOfWays) {
|
||||
|
||||
Tag[] tags = null;
|
||||
Tag[] wayTags = mMapFileHeader.getMapFileInfo().wayTags;
|
||||
Tag[] wayTags = sMapFileHeader.getMapFileInfo().wayTags;
|
||||
int[] textPos = new int[3];
|
||||
// float[] labelPosition;
|
||||
boolean skippedWays = false;
|
||||
@@ -957,7 +964,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
|| cumulatedNumberOfWays > MAXIMUM_ZOOM_TABLE_OBJECTS) {
|
||||
LOG.warning("invalid cumulated number of ways in row " + row + ' '
|
||||
+ cumulatedNumberOfWays);
|
||||
if (mMapFileHeader.getMapFileInfo().debugFile) {
|
||||
if (sMapFileHeader.getMapFileInfo().debugFile) {
|
||||
LOG.warning(DEBUG_SIGNATURE_BLOCK + mSignatureBlock);
|
||||
}
|
||||
return null;
|
||||
|
||||
513
src/org/mapsforge/database/pbmap/MapDatabase.java
Normal file
513
src/org/mapsforge/database/pbmap/MapDatabase.java
Normal file
@@ -0,0 +1,513 @@
|
||||
/*
|
||||
* Copyright 2012 Hannes Janetzek
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.mapsforge.database.pbmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.mapsforge.core.BoundingBox;
|
||||
import org.mapsforge.core.GeoPoint;
|
||||
import org.mapsforge.core.Tag;
|
||||
import org.mapsforge.core.Tile;
|
||||
import org.mapsforge.core.WebMercator;
|
||||
import org.mapsforge.database.FileOpenResult;
|
||||
import org.mapsforge.database.IMapDatabase;
|
||||
import org.mapsforge.database.IMapDatabaseCallback;
|
||||
import org.mapsforge.database.MapFileInfo;
|
||||
|
||||
import android.net.http.AndroidHttpClient;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class MapDatabase implements IMapDatabase {
|
||||
private static final String TAG = "MapDatabase";
|
||||
|
||||
private static final MapFileInfo mMapInfo =
|
||||
new MapFileInfo(new BoundingBox(-180, -90, 180, 90),
|
||||
new Byte((byte) 14), new GeoPoint(53.11, 8.85),
|
||||
WebMercator.NAME, 0, 0, 0, "de", "comment", "author");
|
||||
|
||||
private boolean mOpenFile = false;
|
||||
|
||||
// private static final String URL = "http://city.informatik.uni-bremen.de:8020/test/%d/%d/%d.osmtile";
|
||||
private static final String URL = "http://city.informatik.uni-bremen.de/osmstache/test/%d/%d/%d.osmtile";
|
||||
private static final Header encodingHeader =
|
||||
new BasicHeader("Accept-Encoding", "gzip");
|
||||
|
||||
private static volatile HashMap<String, Tag> tagHash = new HashMap<String, Tag>(100);
|
||||
|
||||
private Tag[] curTags = new Tag[1000];
|
||||
private int mCurTagCnt;
|
||||
|
||||
private AndroidHttpClient mClient;
|
||||
private IMapDatabaseCallback mMapGenerator;
|
||||
private float mScaleFactor;
|
||||
|
||||
@Override
|
||||
public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
|
||||
|
||||
String url = String.format(URL, Integer.valueOf(tile.zoomLevel),
|
||||
Long.valueOf(tile.tileX), Long.valueOf(tile.tileY));
|
||||
|
||||
HttpGet getRequest = new HttpGet(url);
|
||||
getRequest.addHeader(encodingHeader);
|
||||
mMapGenerator = mapDatabaseCallback;
|
||||
mCurTagCnt = 0;
|
||||
// using variable coordinate scalefactor to take advantage of
|
||||
// variable byte encoded integers
|
||||
mScaleFactor = 1 / 100f;
|
||||
if (tile.zoomLevel < 12)
|
||||
mScaleFactor = (float) Math.pow(2, (12 - tile.zoomLevel)) / 100f;
|
||||
|
||||
try {
|
||||
HttpResponse response = mClient.execute(getRequest);
|
||||
final int statusCode = response.getStatusLine().getStatusCode();
|
||||
if (statusCode != HttpStatus.SC_OK) {
|
||||
Log.d(TAG, "Http response " + statusCode);
|
||||
return;
|
||||
}
|
||||
|
||||
final HttpEntity entity = response.getEntity();
|
||||
if (entity == null) {
|
||||
Log.d(TAG, "Somethings wrong? - no entity " + statusCode);
|
||||
return;
|
||||
}
|
||||
|
||||
InputStream is = null;
|
||||
GZIPInputStream zis = null;
|
||||
try {
|
||||
|
||||
is = entity.getContent();
|
||||
zis = new GZIPInputStream(is);
|
||||
|
||||
decode(zis);
|
||||
|
||||
} finally {
|
||||
if (zis != null)
|
||||
zis.close();
|
||||
if (is != null)
|
||||
is.close();
|
||||
entity.consumeContent();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
getRequest.abort();
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMapProjection() {
|
||||
return WebMercator.NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapFileInfo getMapFileInfo() {
|
||||
return mMapInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOpenFile() {
|
||||
return mOpenFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileOpenResult openFile(File mapFile) {
|
||||
mOpenFile = true;
|
||||
mClient = AndroidHttpClient.newInstance("Android");
|
||||
return new FileOpenResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeFile() {
|
||||
mOpenFile = false;
|
||||
if (mClient != null)
|
||||
mClient.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readString(int position) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final int BUFFER_SIZE = 32768;
|
||||
private final byte[] buffer = new byte[BUFFER_SIZE];
|
||||
private int bufferPos;
|
||||
private int bufferSize;
|
||||
private InputStream inputStream;
|
||||
|
||||
private static final int TAG_TILE_TAGS = 1;
|
||||
private static final int TAG_TILE_WAYS = 2;
|
||||
private static final int TAG_TILE_NODES = 3;
|
||||
private static final int TAG_WAY_TAGS = 1;
|
||||
private static final int TAG_WAY_INDEX = 2;
|
||||
private static final int TAG_WAY_COORDS = 3;
|
||||
// private static final int TAG_NODE_TAGS = 1;
|
||||
// private static final int TAG_NODE_COORDS = 2;
|
||||
|
||||
private int bytesRead;
|
||||
|
||||
private boolean decode(InputStream is) throws IOException {
|
||||
inputStream = is;
|
||||
bytesRead = 0;
|
||||
bufferSize = 0;
|
||||
bufferPos = 0;
|
||||
while (true) {
|
||||
// read tag and wire type
|
||||
int val = decodeVarint32();
|
||||
if (val == 0) {
|
||||
// Log.d(TAG, "EOF, all good");
|
||||
return true;
|
||||
}
|
||||
int tag = (val >> 3);
|
||||
// int wireType = (val & 7);
|
||||
// Log.d(TAG, "tile " + tag + " " + wireType);
|
||||
|
||||
switch (tag) {
|
||||
case TAG_TILE_TAGS:
|
||||
decodeTileTags();
|
||||
break;
|
||||
|
||||
case TAG_TILE_WAYS:
|
||||
decodeTileWays();
|
||||
break;
|
||||
|
||||
case TAG_TILE_NODES:
|
||||
decodeTileNodes();
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.d(TAG, "invalid type for tile: " + tag);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean decodeTileTags() throws IOException {
|
||||
String tagString = decodeString();
|
||||
|
||||
Tag tag = tagHash.get(tagString);
|
||||
if (tag == null) {
|
||||
tag = new Tag(tagString);
|
||||
tagHash.put(tagString, tag);
|
||||
}
|
||||
curTags[mCurTagCnt++] = tag;
|
||||
|
||||
// Log.d(TAG, "tag:" + tag);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean decodeTileWays() throws IOException {
|
||||
int bytes = decodeVarint32();
|
||||
|
||||
int end = bytesRead + bytes;
|
||||
int indexCnt = 0;
|
||||
int tagCnt = 0;
|
||||
int coordCnt = 0;
|
||||
while (bytesRead < end) {
|
||||
// read tag and wire type
|
||||
|
||||
int val = decodeVarint32();
|
||||
if (val == 0)
|
||||
break;
|
||||
|
||||
int tag = (val >> 3);
|
||||
// int wireType = val & 7;
|
||||
|
||||
// Log.d(TAG, "way " + tag + " " + wireType + " bytes:" + bytes);
|
||||
|
||||
switch (tag) {
|
||||
case TAG_WAY_TAGS:
|
||||
tagCnt = decodeWayTags();
|
||||
break;
|
||||
|
||||
case TAG_WAY_INDEX:
|
||||
indexCnt = decodeWayIndices();
|
||||
break;
|
||||
|
||||
case TAG_WAY_COORDS:
|
||||
coordCnt = decodeWayCoordinates();
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.d(TAG, "invalid type for way: " + tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (indexCnt == 0 || tagCnt == 0)
|
||||
return false;
|
||||
|
||||
int[] index = new int[indexCnt];
|
||||
|
||||
int sum = 0;
|
||||
for (int i = 0; i < indexCnt; i++) {
|
||||
index[i] = tmpIndices[i] * 2;
|
||||
sum += index[i];
|
||||
}
|
||||
|
||||
Tag[] tags = new Tag[tagCnt];
|
||||
for (int i = 0; i < tagCnt; i++)
|
||||
tags[i] = curTags[tmpTags[i]];
|
||||
|
||||
float[] coords = tmpCoords;
|
||||
int pos = 0;
|
||||
|
||||
if (coordCnt != sum) {
|
||||
Log.d(TAG, "way length is wrong " + coordCnt + " " + sum);
|
||||
return false;
|
||||
}
|
||||
|
||||
float z = mScaleFactor;
|
||||
for (int j = 0, m = indexCnt; j < m; j++) {
|
||||
float lastX = 0;
|
||||
float lastY = 0;
|
||||
|
||||
for (int n = index[j] + pos; pos < n; pos += 2) {
|
||||
lastX = coords[pos] = (coords[pos] * z) + lastX;
|
||||
lastY = coords[pos + 1] = (coords[pos + 1] * z) + lastY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mMapGenerator.renderWay((byte) 0, tags, coords, index, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean decodeTileNodes() throws IOException {
|
||||
int bytes = decodeVarint32();
|
||||
Log.d(TAG, "way nodes " + bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
private int MAX_WAY_COORDS = 32768;
|
||||
private int MAX_WAY_INDICES = 1000;
|
||||
private int[] tmpTags = new int[32];
|
||||
private int[] tmpIndices = new int[MAX_WAY_INDICES];
|
||||
private float[] tmpCoords = new float[MAX_WAY_COORDS];
|
||||
|
||||
// private boolean ensureBufferSize(int size) throws IOException {
|
||||
// if (size > (bufferSize - bufferPos))
|
||||
// readBuffer(size - (bufferSize - bufferPos));
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
|
||||
private int decodeWayTags() throws IOException {
|
||||
int bytes = decodeVarint32();
|
||||
// Log.d(TAG, "way tags: " + bytes);
|
||||
|
||||
int cnt = 0;
|
||||
int end = bytesRead + bytes;
|
||||
|
||||
while (bytesRead < end)
|
||||
tmpTags[cnt++] = decodeVarint32();
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private int decodeWayIndices() throws IOException {
|
||||
int bytes = decodeVarint32();
|
||||
// Log.d(TAG, "way indices: " + bytes);
|
||||
|
||||
int cnt = 0;
|
||||
int end = bytesRead + bytes;
|
||||
|
||||
while (bytesRead < end) {
|
||||
int val = decodeVarint32();
|
||||
if (cnt >= MAX_WAY_INDICES) {
|
||||
|
||||
MAX_WAY_INDICES += 128;
|
||||
Log.d(TAG, "increase indices array " + MAX_WAY_INDICES);
|
||||
int[] tmp = new int[MAX_WAY_INDICES];
|
||||
System.arraycopy(tmpIndices, 0, tmp, 0, cnt);
|
||||
tmpIndices = tmp;
|
||||
}
|
||||
|
||||
tmpIndices[cnt++] = val;
|
||||
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private int decodeWayCoordinates() throws IOException {
|
||||
int bytes = decodeVarint32();
|
||||
|
||||
int cnt = 0;
|
||||
int end = bytesRead + bytes;
|
||||
|
||||
while (bytesRead < end) {
|
||||
int val = decodeZigZag32(decodeVarint32());
|
||||
if (cnt >= MAX_WAY_COORDS) {
|
||||
MAX_WAY_COORDS += 128;
|
||||
Log.d(TAG, "increase coords array " + MAX_WAY_COORDS);
|
||||
float[] tmp = new float[MAX_WAY_COORDS];
|
||||
System.arraycopy(tmpCoords, 0, tmp, 0, cnt);
|
||||
tmpCoords = tmp;
|
||||
}
|
||||
tmpCoords[cnt++] = val;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private void readBuffer() throws IOException {
|
||||
|
||||
int len = inputStream.read(buffer, 0, BUFFER_SIZE);
|
||||
if (len < 0) {
|
||||
buffer[bufferPos] = 0;
|
||||
// Log.d(TAG, " nothing to read... pos " + bufferPos + ", size "
|
||||
// + bufferSize + ", read " + bytesRead);
|
||||
return;
|
||||
}
|
||||
bufferSize = len;
|
||||
bufferPos = 0;
|
||||
|
||||
// Log.d(TAG, "pos " + bufferPos + ", size " + bufferSize + ", read "
|
||||
// + bytesRead);
|
||||
}
|
||||
|
||||
private void readBuffer(int size) throws IOException {
|
||||
if (size < (bufferSize - bufferPos))
|
||||
return;
|
||||
|
||||
if (size > BUFFER_SIZE) {
|
||||
Log.d(TAG, "EEEK too large");
|
||||
// FIXME throw exception, but frankly better sanitize tile data on compilation
|
||||
// this only happen with Strings larger than 32kb
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size - bufferSize) + bufferPos > BUFFER_SIZE) {
|
||||
// copy bytes left to read from buffer to the beginning of buffer
|
||||
System.arraycopy(buffer, bufferPos, buffer, 0, bufferSize - bufferPos);
|
||||
bufferPos = 0;
|
||||
}
|
||||
|
||||
while ((bufferSize - bufferPos) < size) {
|
||||
// read until requested size is available in buffer
|
||||
int len = inputStream.read(buffer, bufferSize, BUFFER_SIZE - bufferSize);
|
||||
if (len < 0) {
|
||||
buffer[bufferSize - 1] = 0; // FIXME is this needed?
|
||||
break;
|
||||
}
|
||||
bufferSize += len;
|
||||
}
|
||||
|
||||
// Log.d(TAG, "needed " + size + " pos " + bufferPos + ", size "
|
||||
// + bufferSize
|
||||
// + ", read " + bytesRead);
|
||||
}
|
||||
|
||||
/* All code below is taken from or based on Google's Protocol Buffers implementation: */
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
private byte readRawByte() throws IOException {
|
||||
if (bufferPos == bufferSize) {
|
||||
readBuffer();
|
||||
}
|
||||
bytesRead++;
|
||||
return buffer[bufferPos++];
|
||||
}
|
||||
|
||||
private int decodeVarint32() throws IOException {
|
||||
byte tmp = readRawByte();
|
||||
if (tmp >= 0) {
|
||||
return tmp;
|
||||
}
|
||||
int result = tmp & 0x7f;
|
||||
if ((tmp = readRawByte()) >= 0) {
|
||||
return result | tmp << 7;
|
||||
}
|
||||
result |= (tmp & 0x7f) << 7;
|
||||
if ((tmp = readRawByte()) >= 0) {
|
||||
return result | tmp << 14;
|
||||
}
|
||||
result |= (tmp & 0x7f) << 14;
|
||||
if ((tmp = readRawByte()) >= 0) {
|
||||
return result | tmp << 21;
|
||||
}
|
||||
result |= (tmp & 0x7f) << 21;
|
||||
result |= (tmp = readRawByte()) << 28;
|
||||
|
||||
if (tmp < 0) {
|
||||
// Discard upper 32 bits.
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (readRawByte() >= 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "EEK malformedVarint");
|
||||
// FIXME throw some poo
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private String decodeString() throws IOException {
|
||||
final int size = decodeVarint32();
|
||||
|
||||
readBuffer(size);
|
||||
|
||||
final String result = new String(buffer, bufferPos, size, "UTF-8");
|
||||
bufferPos += size;
|
||||
bytesRead += size;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
public static int decodeZigZag32(final int n) {
|
||||
return (n >>> 1) ^ -(n & 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,9 +26,9 @@ import java.util.Properties;
|
||||
|
||||
import org.mapsforge.core.BoundingBox;
|
||||
import org.mapsforge.core.GeoPoint;
|
||||
import org.mapsforge.core.WebMercator;
|
||||
import org.mapsforge.core.Tag;
|
||||
import org.mapsforge.core.Tile;
|
||||
import org.mapsforge.core.WebMercator;
|
||||
import org.mapsforge.database.FileOpenResult;
|
||||
import org.mapsforge.database.IMapDatabase;
|
||||
import org.mapsforge.database.IMapDatabaseCallback;
|
||||
@@ -40,7 +40,7 @@ import org.postgresql.PGConnection;
|
||||
*
|
||||
*/
|
||||
public class MapDatabase implements IMapDatabase {
|
||||
private static final String QUERY = "SELECT * FROM __get_tile(?,?,?)";
|
||||
private static final String QUERY = "SELECT tags, geom FROM __get_tile(?,?,?)";
|
||||
|
||||
private final float mScale = 1; // 1000000.0f;
|
||||
|
||||
@@ -55,16 +55,13 @@ public class MapDatabase implements IMapDatabase {
|
||||
new MapFileInfo(new BoundingBox(-180, -85, 180, 85),
|
||||
new Byte((byte) 14), new GeoPoint(53.11, 8.85),
|
||||
WebMercator.NAME,
|
||||
0, 0, 0, "de", "yo!", "hannes");
|
||||
// new MapFileInfo(new BoundingBox(-180, -90, 180, 90),
|
||||
// new Byte((byte) 0), null, "Mercator",
|
||||
// 0, 0, 0, "de", "yo!", "by me");
|
||||
0, 0, 0, "de", "comment", "author");
|
||||
|
||||
private boolean mOpenFile = false;
|
||||
|
||||
private Connection connection = null;
|
||||
private static HashMap<Entry<String, String>, Tag> tagHash = new HashMap<Entry<String, String>, Tag>(
|
||||
100);
|
||||
private static volatile HashMap<Entry<String, String>, Tag> tagHash =
|
||||
new HashMap<Entry<String, String>, Tag>(100);
|
||||
private PreparedStatement prepQuery = null;
|
||||
|
||||
private boolean connect() {
|
||||
@@ -123,7 +120,6 @@ public class MapDatabase implements IMapDatabase {
|
||||
|
||||
byte[] b = null;
|
||||
PGHStore h = null;
|
||||
// long id;
|
||||
|
||||
try {
|
||||
while (r != null && r.next()) {
|
||||
@@ -131,9 +127,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
mCoordPos = 0;
|
||||
|
||||
try {
|
||||
// id = r.getLong(1);
|
||||
|
||||
Object obj = r.getObject(2);
|
||||
Object obj = r.getObject(1);
|
||||
h = null;
|
||||
|
||||
if (obj instanceof PGHStore)
|
||||
@@ -141,7 +135,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
else
|
||||
continue;
|
||||
|
||||
b = r.getBytes(3);
|
||||
b = r.getBytes(2);
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
@@ -184,6 +178,11 @@ public class MapDatabase implements IMapDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMapProjection() {
|
||||
return WebMercator.NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapFileInfo getMapFileInfo() {
|
||||
return mMapInfo;
|
||||
|
||||
Reference in New Issue
Block a user