add GeometryBuffer class to pass data from MapDatabase to TileGenerator

This commit is contained in:
Hannes Janetzek 2013-03-19 00:40:12 +01:00
parent 64da69e5cf
commit 8c8750a833
12 changed files with 380 additions and 449 deletions

View File

@ -0,0 +1,42 @@
package org.oscim.core;
public class GeometryBuffer {
public float[] points;
public short[] index;
public int indexPos;
public int pointPos;
public GeometryBuffer(float[] points, short[] index){
this.points = points;
this.index = index;
}
public GeometryBuffer(int numPoints, int numIndices) {
this.points = new float[numPoints * 2];
this.index = new short[numIndices];
}
public float[] ensurePointSize(int size, boolean copy){
if (size * 2 < points.length)
return points;
float[] tmp = new float[size * 2 + 1024];
if (copy)
System.arraycopy(tmp, 0, points, 0, points.length);
points = tmp;
return points;
}
public short[] ensureIndexSize(int size, boolean copy){
if (size < index.length)
return index;
short[] tmp = new short[size + 128];
if (copy)
System.arraycopy(tmp, 0, index, 0, index.length);
index = tmp;
return index;
}
}

View File

@ -14,6 +14,7 @@
*/ */
package org.oscim.database; package org.oscim.database;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.database.mapfile.MapDatabase; import org.oscim.database.mapfile.MapDatabase;
@ -36,7 +37,7 @@ public interface IMapDatabaseCallback {
* @param longitude * @param longitude
* the longitude of the node. * the longitude of the node.
*/ */
void renderPointOfInterest(byte layer, Tag[] tags, float latitude, float longitude); void renderPOI(byte layer, Tag[] tags, GeometryBuffer geom);
/** /**
* Renders water background for the current tile. * Renders water background for the current tile.
@ -59,7 +60,7 @@ public interface IMapDatabaseCallback {
* wheter the way is an polygon. * wheter the way is an polygon.
* @param prio TODO * @param prio TODO
*/ */
void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLength, void renderWay(byte layer, Tag[] tags, GeometryBuffer geom,
boolean closed, int prio); boolean closed, int prio);
// /** // /**

View File

@ -18,6 +18,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.MercatorProjection; import org.oscim.core.MercatorProjection;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.Tile; import org.oscim.core.Tile;
@ -197,8 +198,7 @@ public class MapDatabase implements IMapDatabase {
private int mTileLongitude; private int mTileLongitude;
private int[] mIntBuffer; private int[] mIntBuffer;
private final float[] mWayNodes = new float[100000]; private final GeometryBuffer mGeom = new GeometryBuffer(1 << 14, 1 << 8);
private int mWayNodePosition;
private int minLat, minLon; private int minLat, minLon;
private Tile mTile; private Tile mTile;
@ -219,8 +219,6 @@ public class MapDatabase implements IMapDatabase {
if (mIntBuffer == null) if (mIntBuffer == null)
mIntBuffer = new int[MAXIMUM_WAY_NODES_SEQUENCE_LENGTH * 2]; mIntBuffer = new int[MAXIMUM_WAY_NODES_SEQUENCE_LENGTH * 2];
mWayNodePosition = 0;
try { try {
mTile = tile; mTile = tile;
@ -669,24 +667,30 @@ public class MapDatabase implements IMapDatabase {
double sinLat = Math.sin(latitude * PI180); double sinLat = Math.sin(latitude * PI180);
latitude = (int) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy); latitude = (int) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
mapDatabaseCallback.renderPointOfInterest(layer, curTags, latitude, longitude); mGeom.points[0] = longitude;
mGeom.points[1] = latitude;
mGeom.index[0] = 2;
mapDatabaseCallback.renderPOI(layer, curTags, mGeom);
} }
return true; return true;
} }
private short[] processWayDataBlock(boolean doubleDeltaEncoding) { private boolean processWayDataBlock(boolean doubleDeltaEncoding) {
// get and check the number of way coordinate blocks (VBE-U) // get and check the number of way coordinate blocks (VBE-U)
int numBlocks = mReadBuffer.readUnsignedInt(); int numBlocks = mReadBuffer.readUnsignedInt();
if (numBlocks < 1 || numBlocks > Short.MAX_VALUE) { if (numBlocks < 1 || numBlocks > Short.MAX_VALUE) {
Log.w(TAG, "invalid number of way coordinate blocks: " + numBlocks); Log.w(TAG, "invalid number of way coordinate blocks: " + numBlocks);
return null; return false;
} }
short[] wayLengths = new short[numBlocks]; //short[] wayLengths = new short[numBlocks];
short[] wayLengths = mGeom.ensureIndexSize(numBlocks, false);
if (wayLengths.length > numBlocks)
wayLengths[numBlocks] = -1;
mWayNodePosition = 0; mGeom.pointPos = 0;
// read the way coordinate blocks // read the way coordinate blocks
for (int coordinateBlock = 0; coordinateBlock < numBlocks; ++coordinateBlock) { for (int coordinateBlock = 0; coordinateBlock < numBlocks; ++coordinateBlock) {
@ -696,7 +700,7 @@ public class MapDatabase implements IMapDatabase {
if (numWayNodes < 2 || numWayNodes > MAXIMUM_WAY_NODES_SEQUENCE_LENGTH) { if (numWayNodes < 2 || numWayNodes > MAXIMUM_WAY_NODES_SEQUENCE_LENGTH) {
Log.w(TAG, "invalid number of way nodes: " + numWayNodes); Log.w(TAG, "invalid number of way nodes: " + numWayNodes);
logDebugSignatures(); logDebugSignatures();
return null; return false;
} }
// each way node consists of latitude and longitude // each way node consists of latitude and longitude
@ -710,16 +714,16 @@ public class MapDatabase implements IMapDatabase {
wayLengths[coordinateBlock] = (short) len; wayLengths[coordinateBlock] = (short) len;
} }
return wayLengths; return true;
} }
private int decodeWayNodesDoubleDelta(int length) { private int decodeWayNodesDoubleDelta(int length) {
int[] buffer = mIntBuffer; int[] buffer = mIntBuffer;
float[] outBuffer = mWayNodes;
mReadBuffer.readSignedInt(buffer, length); mReadBuffer.readSignedInt(buffer, length);
int floatPos = mWayNodePosition; float[] outBuffer = mGeom.ensurePointSize(mGeom.pointPos + length, true);
int pointPos = mGeom.pointPos;
// get the first way node latitude offset (VBE-S) // get the first way node latitude offset (VBE-S)
int wayNodeLatitude = mTileLatitude + buffer[0]; int wayNodeLatitude = mTileLatitude + buffer[0];
@ -728,8 +732,8 @@ public class MapDatabase implements IMapDatabase {
int wayNodeLongitude = mTileLongitude + buffer[1]; int wayNodeLongitude = mTileLongitude + buffer[1];
// store the first way node // store the first way node
outBuffer[floatPos++] = wayNodeLongitude; outBuffer[pointPos++] = wayNodeLongitude;
outBuffer[floatPos++] = wayNodeLatitude; outBuffer[pointPos++] = wayNodeLatitude;
int singleDeltaLatitude = 0; int singleDeltaLatitude = 0;
int singleDeltaLongitude = 0; int singleDeltaLongitude = 0;
@ -750,23 +754,23 @@ public class MapDatabase implements IMapDatabase {
if (dLon > minLon || dLon < -minLon || dLat > minLat || dLat < -minLat if (dLon > minLon || dLon < -minLon || dLat > minLat || dLat < -minLat
|| (pos == length - 2)) { || (pos == length - 2)) {
outBuffer[floatPos++] = nLon; outBuffer[pointPos++] = nLon;
outBuffer[floatPos++] = nLat; outBuffer[pointPos++] = nLat;
cnt += 2; cnt += 2;
} }
} }
mWayNodePosition = floatPos; mGeom.pointPos = pointPos;
return cnt; return cnt;
} }
private int decodeWayNodesSingleDelta(int length) { private int decodeWayNodesSingleDelta(int length) {
int[] buffer = mIntBuffer; int[] buffer = mIntBuffer;
float[] outBuffer = mWayNodes;
mReadBuffer.readSignedInt(buffer, length); mReadBuffer.readSignedInt(buffer, length);
int floatPos = mWayNodePosition; float[] outBuffer = mGeom.ensurePointSize(mGeom.pointPos + length, true);
int pointPos = mGeom.pointPos;
// get the first way node latitude single-delta offset (VBE-S) // get the first way node latitude single-delta offset (VBE-S)
int wayNodeLatitude = mTileLatitude + buffer[0]; int wayNodeLatitude = mTileLatitude + buffer[0];
@ -775,8 +779,8 @@ public class MapDatabase implements IMapDatabase {
int wayNodeLongitude = mTileLongitude + buffer[1]; int wayNodeLongitude = mTileLongitude + buffer[1];
// store the first way node // store the first way node
outBuffer[floatPos++] = wayNodeLongitude; outBuffer[pointPos++] = wayNodeLongitude;
outBuffer[floatPos++] = wayNodeLatitude; outBuffer[pointPos++] = wayNodeLatitude;
int cnt = 2, nLon, nLat, dLat, dLon; int cnt = 2, nLon, nLat, dLat, dLon;
@ -792,13 +796,13 @@ public class MapDatabase implements IMapDatabase {
if (dLon > minLon || dLon < -minLon || dLat > minLat || dLat < -minLat if (dLon > minLon || dLon < -minLon || dLat > minLat || dLat < -minLat
|| (pos == length - 2)) { || (pos == length - 2)) {
outBuffer[floatPos++] = nLon; outBuffer[pointPos++] = nLon;
outBuffer[floatPos++] = nLat; outBuffer[pointPos++] = nLat;
cnt += 2; cnt += 2;
} }
} }
mWayNodePosition = floatPos; mGeom.pointPos = pointPos;
return cnt; return cnt;
} }
@ -965,18 +969,17 @@ public class MapDatabase implements IMapDatabase {
} }
for (int wayDataBlock = 0; wayDataBlock < wayDataBlocks; ++wayDataBlock) { for (int wayDataBlock = 0; wayDataBlock < wayDataBlocks; ++wayDataBlock) {
short[] wayLengths = processWayDataBlock(featureWayDoubleDeltaEncoding); if (!processWayDataBlock(featureWayDoubleDeltaEncoding))
if (wayLengths == null)
return false; return false;
// wayDataContainer.textPos = textPos; // wayDataContainer.textPos = textPos;
int l = wayLengths[0]; int l = mGeom.index[0];
boolean closed = mWayNodes[0] == mWayNodes[l - 2] boolean closed = mGeom.points[0] == mGeom.points[l - 2]
&& mWayNodes[1] == mWayNodes[l - 1]; && mGeom.points[1] == mGeom.points[l - 1];
projectToTile(mWayNodes, wayLengths); projectToTile(mGeom.points, mGeom.index);
mapDatabaseCallback.renderWay(layer, curTags, mWayNodes, wayLengths, closed, 0); mapDatabaseCallback.renderWay(layer, curTags, mGeom, closed, 0);
} }
} }

View File

@ -23,6 +23,7 @@ import java.util.Arrays;
import org.oscim.core.BoundingBox; import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint; import org.oscim.core.GeoPoint;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.database.IMapDatabase; import org.oscim.database.IMapDatabase;
@ -207,7 +208,7 @@ public class MapDatabase implements IMapDatabase {
} }
// /////////////// hand sewed tile protocol buffers decoder /////////////// // /////////////// hand sewed tile protocol buffers decoder ///////////////
private final int MAX_WAY_COORDS = 16384; private final int MAX_WAY_COORDS = 1 << 14;
// overall bytes of content processed // overall bytes of content processed
private int mBytesProcessed; private int mBytesProcessed;
@ -230,10 +231,11 @@ public class MapDatabase implements IMapDatabase {
private static final int TAG_ELEM_PRIORITY = 31; private static final int TAG_ELEM_PRIORITY = 31;
private short[] mTmpKeys = new short[100]; private short[] mTmpKeys = new short[100];
private short[] mIndices = new short[10];
private final Tag[] mTmpTags = new Tag[20]; private final Tag[] mTmpTags = new Tag[20];
private float[] mTmpCoords; //private float[] mTmpCoords;
//private short[] mIndices = new short[10];
private final GeometryBuffer mGeom = new GeometryBuffer(MAX_WAY_COORDS, 128);
private Tag[][] mElementTags; private Tag[][] mElementTags;
@ -243,8 +245,6 @@ public class MapDatabase implements IMapDatabase {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
tags[i] = new Tag[i + 1]; tags[i] = new Tag[i + 1];
mElementTags = tags; mElementTags = tags;
mTmpCoords = new float[MAX_WAY_COORDS];
} }
private boolean decode() throws IOException { private boolean decode() throws IOException {
@ -309,25 +309,43 @@ public class MapDatabase implements IMapDatabase {
return true; return true;
} }
private boolean decodeTileElement(int type) throws IOException { private int decodeWayIndices(int indexCnt) throws IOException {
int bytes = decodeVarint32(); mGeom.index = decodeShortArray(indexCnt, mGeom.index);
int end = mBytesProcessed + bytes; short[] index = mGeom.index;
int indexCnt = 1;
int coordCnt = 0; int coordCnt = 0;
int layer = 5;
int prio = 0;
for (int i = 0; i < indexCnt; i++) {
int len = index[i] * 2;
coordCnt += len;
index[i] = (short) len;
}
// set end marker
if (indexCnt < index.length)
index[indexCnt] = -1;
return coordCnt;
}
private boolean decodeTileElement(int type) throws IOException {
int bytes = decodeVarint32();
Tag[] tags = null; Tag[] tags = null;
short[] index = null; short[] index = null;
int end = mBytesProcessed + bytes;
int indexCnt = 1;
int layer = 5;
int prio = 0;
boolean skip = false; boolean skip = false;
boolean fail = false; boolean fail = false;
if (debug)
Log.d(TAG, mTile + " decode element: " + type);
if (type == TAG_TILE_POINT) int coordCnt = 0;
if (type == TAG_TILE_POINT){
coordCnt = 2; coordCnt = 2;
mGeom.index[0] = 2;
}
while (mBytesProcessed < end) { while (mBytesProcessed < end) {
// read tag and wire type // read tag and wire type
@ -347,16 +365,7 @@ public class MapDatabase implements IMapDatabase {
break; break;
case TAG_ELEM_INDEX: case TAG_ELEM_INDEX:
mIndices = index = decodeShortArray(indexCnt, mIndices); coordCnt = decodeWayIndices(indexCnt);
for (int i = 0; i < indexCnt; i++) {
int len = index[i] * 2;
coordCnt += len;
index[i] = (short) len;
}
// set end marker
if (indexCnt < index.length)
index[indexCnt] = -1;
break; break;
case TAG_ELEM_COORDS: case TAG_ELEM_COORDS:
@ -387,20 +396,22 @@ public class MapDatabase implements IMapDatabase {
if (fail || tags == null || indexCnt == 0) { if (fail || tags == null || indexCnt == 0) {
Log.d(TAG, mTile + " failed reading way: bytes:" + bytes + " index:" Log.d(TAG, mTile + " failed reading way: bytes:" + bytes + " index:"
+ (index != null ? Arrays.toString(index) : "null") + " tag:" + (Arrays.toString(index)) + " tag:"
+ (tags != null ? Arrays.deepToString(tags) : "null") + " " + (tags != null ? Arrays.deepToString(tags) : "null") + " "
+ indexCnt + " " + coordCnt); + indexCnt + " " + coordCnt);
return false; return false;
} }
float[] coords = mTmpCoords; switch (type) {
case TAG_TILE_LINE:
if (type == TAG_TILE_LINE) mMapGenerator.renderWay((byte) layer, tags, mGeom, false, prio);
mMapGenerator.renderWay((byte) layer, tags, coords, index, false, prio); break;
else if (type == TAG_TILE_POLY) case TAG_TILE_POLY:
mMapGenerator.renderWay((byte) layer, tags, coords, index, true, prio); mMapGenerator.renderWay((byte) layer, tags, mGeom, true, prio);
else { break;
mMapGenerator.renderPointOfInterest((byte) layer, tags, coords[1], coords[0]); case TAG_TILE_POINT:
mMapGenerator.renderPOI((byte) layer, tags, mGeom);
break;
} }
return true; return true;
@ -463,7 +474,6 @@ public class MapDatabase implements IMapDatabase {
int pos = lwHttp.bufferPos; int pos = lwHttp.bufferPos;
int end = pos + bytes; int end = pos + bytes;
float[] coords = mTmpCoords;
byte[] buf = lwHttp.buffer; byte[] buf = lwHttp.buffer;
int cnt = 0; int cnt = 0;
int result; int result;
@ -474,11 +484,13 @@ public class MapDatabase implements IMapDatabase {
float scale = mScaleFactor; float scale = mScaleFactor;
if (nodes * 2 > coords.length) { float[] coords = mGeom.ensurePointSize(nodes, false);
Log.d(TAG, mTile + " increase way coord buffer to " + (nodes * 2));
float[] tmp = new float[nodes * 2]; // if (nodes * 2 > coords.length) {
mTmpCoords = coords = tmp; // Log.d(TAG, mTile + " increase way coord buffer to " + (nodes * 2));
} // float[] tmp = new float[nodes * 2];
// mTmpCoords = coords = tmp;
// }
// read repeated sint32 // read repeated sint32
while (pos < end) { while (pos < end) {

View File

@ -36,6 +36,7 @@ import java.util.Map;
import org.oscim.core.BoundingBox; import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint; import org.oscim.core.GeoPoint;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.database.IMapDatabase; import org.oscim.database.IMapDatabase;
@ -89,9 +90,6 @@ public class MapDatabase implements IMapDatabase {
private Tag[] curTags = new Tag[MAX_TILE_TAGS]; private Tag[] curTags = new Tag[MAX_TILE_TAGS];
private int mCurTagCnt; private int mCurTagCnt;
// private HttpClient mClient;
// private HttpGet mRequest = null;
private IMapDatabaseCallback mMapGenerator; private IMapDatabaseCallback mMapGenerator;
private float mScaleFactor; private float mScaleFactor;
private JobTile mTile; private JobTile mTile;
@ -147,76 +145,13 @@ public class MapDatabase implements IMapDatabase {
return QueryResult.SUCCESS; return QueryResult.SUCCESS;
} }
// String url = null;
// HttpGet getRequest;
// if (!USE_LW_HTTP) {
// url = String.format(URL,
// Integer.valueOf(tile.zoomLevel),
// Integer.valueOf(tile.tileX),
// Integer.valueOf(tile.tileY));
// }
// if (USE_APACHE_HTTP) {
// getRequest = new HttpGet(url);
// mRequest = getRequest;
// }
try { try {
// if (USE_LW_HTTP) {
if (lwHttpSendRequest(tile) && lwHttpReadHeader() > 0) { if (lwHttpSendRequest(tile) && lwHttpReadHeader() > 0) {
cacheBegin(tile, f); cacheBegin(tile, f);
decode(); decode();
} else { } else {
result = QueryResult.FAILED; result = QueryResult.FAILED;
} }
// }
// else if (USE_APACHE_HTTP) {
// HttpResponse response = mClient.execute(getRequest);
// final int statusCode = response.getStatusLine().getStatusCode();
// final HttpEntity entity = response.getEntity();
//
// if (statusCode != HttpStatus.SC_OK) {
// Log.d(TAG, "Http response " + statusCode);
// entity.consumeContent();
// return QueryResult.FAILED;
// }
// if (!mTile.isLoading) {
// Log.d(TAG, "1 loading canceled " + mTile);
// entity.consumeContent();
//
// return QueryResult.FAILED;
// }
//
// InputStream is = null;
// // GZIPInputStream zis = null;
// try {
// is = entity.getContent();
//
// mContentLenth = entity.getContentLength();
// mInputStream = is;
// cacheBegin(tile, f);
// // zis = new GZIPInputStream(is);
// decode();
// } finally {
// // if (zis != null)
// // zis.close();
// if (is != null)
// is.close();
// entity.consumeContent();
// }
// } else {
// HttpURLConnection urlConn =
// (HttpURLConnection) new URL(url).openConnection();
//
// InputStream in = urlConn.getInputStream();
// try {
// decode();
// } finally {
// urlConn.disconnect();
// }
// }
} catch (SocketException ex) { } catch (SocketException ex) {
Log.d(TAG, "Socket exception: " + ex.getMessage()); Log.d(TAG, "Socket exception: " + ex.getMessage());
result = QueryResult.FAILED; result = QueryResult.FAILED;
@ -233,9 +168,6 @@ public class MapDatabase implements IMapDatabase {
mLastRequest = SystemClock.elapsedRealtime(); mLastRequest = SystemClock.elapsedRealtime();
// if (USE_APACHE_HTTP)
// mRequest = null;
cacheFinish(tile, f, result == QueryResult.SUCCESS); cacheFinish(tile, f, result == QueryResult.SUCCESS);
return result; return result;
@ -258,37 +190,9 @@ public class MapDatabase implements IMapDatabase {
return mOpenFile; return mOpenFile;
} }
// private void createClient() {
// mOpenFile = true;
// HttpParams params = new BasicHttpParams();
// HttpConnectionParams.setStaleCheckingEnabled(params, false);
// HttpConnectionParams.setTcpNoDelay(params, true);
// HttpConnectionParams.setConnectionTimeout(params, 20 * 1000);
// HttpConnectionParams.setSoTimeout(params, 60 * 1000);
// HttpConnectionParams.setSocketBufferSize(params, 32768);
// HttpClientParams.setRedirecting(params, false);
//
// DefaultHttpClient client = new DefaultHttpClient(params);
// client.removeRequestInterceptorByClass(RequestAddCookies.class);
// client.removeResponseInterceptorByClass(ResponseProcessCookies.class);
// client.removeRequestInterceptorByClass(RequestUserAgent.class);
// client.removeRequestInterceptorByClass(RequestExpectContinue.class);
// client.removeRequestInterceptorByClass(RequestTargetAuthentication.class);
// client.removeRequestInterceptorByClass(RequestProxyAuthentication.class);
//
// mClient = client;
//
// SchemeRegistry schemeRegistry = new SchemeRegistry();
// schemeRegistry.register(new Scheme("http",
// PlainSocketFactory.getSocketFactory(), 80));
// }
@Override @Override
public OpenResult open(MapOptions options) { public OpenResult open(MapOptions options) {
//if (USE_APACHE_HTTP)
// createClient();
if (mOpenFile) if (mOpenFile)
return OpenResult.SUCCESS; return OpenResult.SUCCESS;
@ -344,15 +248,6 @@ public class MapDatabase implements IMapDatabase {
@Override @Override
public void close() { public void close() {
mOpenFile = false; mOpenFile = false;
// if (USE_APACHE_HTTP) {
// if (mClient != null) {
// mClient.getConnectionManager().shutdown();
// mClient = null;
// }
// }
// if (USE_LW_HTTP) {
mSockAddr = null; mSockAddr = null;
if (mSocket != null) { if (mSocket != null) {
@ -363,7 +258,7 @@ public class MapDatabase implements IMapDatabase {
} }
mSocket = null; mSocket = null;
} }
// }
if (USE_CACHE) { if (USE_CACHE) {
cacheDir = null; cacheDir = null;
} }
@ -384,17 +279,6 @@ public class MapDatabase implements IMapDatabase {
} }
// /////////////// hand sewed tile protocol buffers decoder //////////////// // /////////////// hand sewed tile protocol buffers decoder ////////////////
private static final int BUFFER_SIZE = 65536;
private final byte[] mReadBuffer = new byte[BUFFER_SIZE];
// position in read buffer
private int mBufferPos;
// bytes available in read buffer
private int mBufferSize;
// overall bytes of content processed
private int mBytesProcessed;
private static final int TAG_TILE_TAGS = 1; private static final int TAG_TILE_TAGS = 1;
private static final int TAG_TILE_WAYS = 2; private static final int TAG_TILE_WAYS = 2;
private static final int TAG_TILE_POLY = 3; private static final int TAG_TILE_POLY = 3;
@ -413,6 +297,20 @@ public class MapDatabase implements IMapDatabase {
private static final int TAG_NODE_NUM_TAGS = 1; private static final int TAG_NODE_NUM_TAGS = 1;
private static final int TAG_NODE_NUM_COORDS = 2; private static final int TAG_NODE_NUM_COORDS = 2;
private static final int BUFFER_SIZE = 65536;
private final byte[] mReadBuffer = new byte[BUFFER_SIZE];
// position in read buffer
private int mBufferPos;
// bytes available in read buffer
private int mBufferSize;
// overall bytes of content processed
private int mBytesProcessed;
private final GeometryBuffer mGeom = new GeometryBuffer(1 << 14, 1 << 8);
private boolean decode() throws IOException { private boolean decode() throws IOException {
mBytesProcessed = 0; mBytesProcessed = 0;
int val; int val;
@ -544,19 +442,16 @@ public class MapDatabase implements IMapDatabase {
if (fail || index == null || tags == null || indexCnt == 0 || tagCnt == 0) { if (fail || index == null || tags == null || indexCnt == 0 || tagCnt == 0) {
Log.d(TAG, "failed reading way: bytes:" + bytes + " index:" Log.d(TAG, "failed reading way: bytes:" + bytes + " index:"
+ (index == null ? "null" : index.toString()) + " tag:"
+ (tags != null ? tags.toString() : "...") + " " + (tags != null ? tags.toString() : "...") + " "
+ indexCnt + " " + coordCnt + " " + tagCnt); + indexCnt + " " + coordCnt + " " + tagCnt);
return false; return false;
} }
float[] coords = tmpCoords;
// FIXME, remove all tiles from cache then remove this below // FIXME, remove all tiles from cache then remove this below
if (layer == 0) if (layer == 0)
layer = 5; layer = 5;
mMapGenerator.renderWay((byte) layer, tags, coords, index, polygon, 0); mMapGenerator.renderWay((byte) layer, tags, mGeom, polygon, 0);
return true; return true;
} }
@ -621,22 +516,23 @@ public class MapDatabase implements IMapDatabase {
// read repeated sint32 // read repeated sint32
int lastX = 0; int lastX = 0;
int lastY = 0; int lastY = 0;
float[] coords = mGeom.ensurePointSize(numNodes, false);
while (mBytesProcessed < end && cnt < numNodes) { while (mBytesProcessed < end && cnt < numNodes) {
int lon = decodeZigZag32(decodeVarint32()); int lon = decodeZigZag32(decodeVarint32());
int lat = decodeZigZag32(decodeVarint32()); int lat = decodeZigZag32(decodeVarint32());
lastX = lon + lastX; lastX = lon + lastX;
lastY = lat + lastY; lastY = lat + lastY;
coords[cnt++] = lastX / scale;
mMapGenerator.renderPointOfInterest(layer, coords[cnt++] = Tile.TILE_SIZE - lastY / scale;
tags, Tile.TILE_SIZE - lastY / scale, lastX / scale);
cnt += 2;
} }
mGeom.index[0] = (short)numNodes;
mMapGenerator.renderPOI(layer, tags, mGeom);
return cnt; return cnt;
} }
private int MAX_WAY_COORDS = 32768;
private float[] tmpCoords = new float[MAX_WAY_COORDS];
private Tag[] decodeWayTags(int tagCnt) throws IOException { private Tag[] decodeWayTags(int tagCnt) throws IOException {
int bytes = decodeVarint32(); int bytes = decodeVarint32();
@ -676,15 +572,15 @@ public class MapDatabase implements IMapDatabase {
return tags; return tags;
} }
private short[] mIndices = new short[10];
private short[] decodeWayIndices(int indexCnt) throws IOException { private short[] decodeWayIndices(int indexCnt) throws IOException {
int bytes = decodeVarint32(); int bytes = decodeVarint32();
short[] index = mIndices; short[] index = mGeom.ensureIndexSize(indexCnt, false);
if (index.length < indexCnt + 1) {
index = mIndices = new short[indexCnt + 1]; // mIndices;
} // if (index.length < indexCnt + 1) {
// index = mIndices = new short[indexCnt + 1];
// }
readBuffer(bytes); readBuffer(bytes);
@ -762,22 +658,16 @@ public class MapDatabase implements IMapDatabase {
int pos = mBufferPos; int pos = mBufferPos;
int end = pos + bytes; int end = pos + bytes;
float[] coords = tmpCoords;
byte[] buf = mReadBuffer; byte[] buf = mReadBuffer;
int cnt = 0; int cnt = 0;
int result; int result;
float scale = mScaleFactor;
int x, lastX = 0; int x, lastX = 0;
int y, lastY = 0; int y, lastY = 0;
boolean even = true; boolean even = true;
float scale = mScaleFactor; float[] coords = mGeom.ensurePointSize(nodes, false);
if (nodes * 2 > coords.length) {
Log.d(TAG, "increase way coord buffer " + mTile + " to " + (nodes * 2));
float[] tmp = new float[nodes * 2];
tmpCoords = coords = tmp;
}
// read repeated sint32 // read repeated sint32
while (pos < end) { while (pos < end) {

View File

@ -25,6 +25,7 @@ import java.util.Properties;
import org.oscim.core.BoundingBox; import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint; import org.oscim.core.GeoPoint;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.WebMercator; import org.oscim.core.WebMercator;
import org.oscim.database.IMapDatabase; import org.oscim.database.IMapDatabase;
@ -49,10 +50,11 @@ public class MapDatabase implements IMapDatabase {
private final float mScale = 1; private final float mScale = 1;
private int mCoordPos = 0; // private int mCoordPos = 0;
private int mIndexPos = 0; // private int mIndexPos = 0;
private float[] mCoords; // private float[] mCoords;
private short[] mIndex; // private short[] mIndex;
private final GeometryBuffer mGeom = new GeometryBuffer(1 << 14, 1 << 8);
private Tag[] mTags; private Tag[] mTags;
@ -128,8 +130,8 @@ public class MapDatabase implements IMapDatabase {
// int cnt = 0; // int cnt = 0;
try { try {
while (r != null && r.next()) { while (r != null && r.next()) {
mIndexPos = 0; mGeom.indexPos = 0;
mCoordPos = 0; mGeom.pointPos =0;
// cnt++; // cnt++;
try { try {
Object obj = r.getObject(1); Object obj = r.getObject(1);
@ -172,17 +174,20 @@ public class MapDatabase implements IMapDatabase {
continue; continue;
boolean polygon = parse(b); boolean polygon = parse(b);
if (mIndexPos == 0) { if (mGeom.indexPos == 0) {
Log.d(TAG, "no index: skip way"); Log.d(TAG, "no index: skip way");
continue; continue;
} else if (mIndexPos == 1) { } else if (mGeom.indexPos == 1) {
mapDatabaseCallback.renderPointOfInterest((byte) 0, mTags, mapDatabaseCallback.renderPOI((byte) 0, mTags, mGeom);
mCoords[1], mCoords[0]);
} else { } else {
short[] idx = new short[mIndexPos]; // short[] idx = new short[mIndexPos];
System.arraycopy(mIndex, 0, idx, 0, mIndexPos); // System.arraycopy(mIndex, 0, idx, 0, mIndexPos);
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, idx, polygon, 0); //
if (mGeom.index.length > mGeom.indexPos)
mGeom.index[mGeom.indexPos] = -1;
mapDatabaseCallback.renderWay((byte) 0, mTags, mGeom, polygon, 0);
} }
} }
} catch (SQLException e) { } catch (SQLException e) {
@ -212,10 +217,6 @@ public class MapDatabase implements IMapDatabase {
@Override @Override
public OpenResult open(MapOptions options) { public OpenResult open(MapOptions options) {
mOpenFile = true; mOpenFile = true;
if (mCoords == null) {
mCoords = new float[100000];
mIndex = new short[100000];
}
return OpenResult.SUCCESS; return OpenResult.SUCCESS;
} }
@ -230,8 +231,6 @@ public class MapDatabase implements IMapDatabase {
connection = null; connection = null;
} }
} }
mCoords = null;
mIndex = null;
mOpenFile = false; mOpenFile = false;
} }
@ -315,10 +314,11 @@ public class MapDatabase implements IMapDatabase {
private void parsePoint(ValueGetter data, boolean haveZ, boolean haveM) { private void parsePoint(ValueGetter data, boolean haveZ, boolean haveM) {
// double X = data.getDouble(); // double X = data.getDouble();
// double Y = data.getDouble(); // double Y = data.getDouble();
mCoords[0] = (float) (data.getDouble() * mScale); mGeom.points[0] = (float) (data.getDouble() * mScale);
mCoords[1] = (float) (data.getDouble() * mScale); mGeom.points[1] = (float) (data.getDouble() * mScale);
mIndex[0] = 2; mGeom.index[0] = 2;
mIndexPos = 1; mGeom.indexPos= 1;
if (haveZ) if (haveZ)
data.getDouble(); data.getDouble();
@ -338,7 +338,7 @@ public class MapDatabase implements IMapDatabase {
private void parseGeometryArray(ValueGetter data, int count) { private void parseGeometryArray(ValueGetter data, int count) {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
parseGeometry(data); parseGeometry(data);
mIndex[mIndexPos++] = 0; mGeom.index[mGeom.indexPos++] = 0;
} }
} }
@ -357,14 +357,14 @@ public class MapDatabase implements IMapDatabase {
private void parseLineString(ValueGetter data, boolean haveZ, boolean haveM) { private void parseLineString(ValueGetter data, boolean haveZ, boolean haveM) {
int count = data.getInt(); int count = data.getInt();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
mCoords[mCoordPos++] = (float) (data.getDouble()) * mScale; mGeom.points[mGeom.pointPos++] = (float) (data.getDouble()) * mScale;
mCoords[mCoordPos++] = (float) (data.getDouble()) * mScale; mGeom.points[mGeom.pointPos++] = (float) (data.getDouble()) * mScale;
if (haveZ) if (haveZ)
data.getDouble(); data.getDouble();
if (haveM) if (haveM)
data.getDouble(); data.getDouble();
} }
mIndex[mIndexPos++] = (short) (count * 2); mGeom.index[mGeom.indexPos++] = (short) (count * 2);
} }
private void parsePolygon(ValueGetter data, boolean haveZ, boolean haveM) { private void parsePolygon(ValueGetter data, boolean haveZ, boolean haveM) {

View File

@ -15,6 +15,7 @@
package org.oscim.database.test; package org.oscim.database.test;
import org.oscim.core.BoundingBox; import org.oscim.core.BoundingBox;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.database.IMapDatabase; import org.oscim.database.IMapDatabase;
@ -32,18 +33,21 @@ import org.oscim.generator.JobTile;
public class MapDatabase implements IMapDatabase { public class MapDatabase implements IMapDatabase {
private final static String PROJECTION = "Mercator"; private final static String PROJECTION = "Mercator";
private float[] mCoords = new float[20]; //private float[] mCoords = new float[20];
private short[] mIndex = new short[4]; //private short[] mIndex = new short[4];
GeometryBuffer mGeom = new GeometryBuffer(new float[20], new short[4]);
// private Tag[] mTags = { new Tag("boundary", "administrative"), new // private Tag[] mTags = { new Tag("boundary", "administrative"), new
// Tag("admin_level", "2") }; // Tag("admin_level", "2") };
private Tag[] mTags = { new Tag("natural", "water") }; private final Tag[] mTags = { new Tag("natural", "water") };
private Tag[] mTagsWay = { new Tag("highway", "primary"), new Tag("name", "Highway Rd") }; private final Tag[] mTagsWay = { new Tag("highway", "primary"), new Tag("name", "Highway Rd") };
// private Tag[] mNameTags; // private Tag[] mNameTags;
private final MapInfo mMapInfo = private final MapInfo mMapInfo =
new MapInfo(new BoundingBox(-180, -90, 180, 90), new MapInfo(new BoundingBox(-180, -90, 180, 90),
new Byte((byte) 0), null, PROJECTION, 0, 0, 0, "de", "yo!", "by me", new Byte((byte) 5), null, PROJECTION, 0, 0, 0, "de", "yo!", "by me",
null); null);
private boolean mOpenFile = false; private boolean mOpenFile = false;
@ -52,118 +56,102 @@ public class MapDatabase implements IMapDatabase {
public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) { public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
int size = Tile.TILE_SIZE; int size = Tile.TILE_SIZE;
float[] points = mGeom.points;
short[] index = mGeom.index;
float lat1 = -1; float lat1 = -1;
float lon1 = -1; float lon1 = -1;
float lat2 = size + 1; float lat2 = size + 1;
float lon2 = size + 1; float lon2 = size + 1;
mCoords[0] = lon1; points[0] = lon1;
mCoords[1] = lat1; points[1] = lat1;
mCoords[2] = lon2; points[2] = lon2;
mCoords[3] = lat1; points[3] = lat1;
mCoords[4] = lon2; points[4] = lon2;
mCoords[5] = lat2; points[5] = lat2;
mCoords[6] = lon1; points[6] = lon1;
mCoords[7] = lat2; points[7] = lat2;
mCoords[8] = lon1; points[8] = lon1;
mCoords[9] = lat1; points[9] = lat1;
mIndex[0] = 10; index[0] = 10;
mIndex[1] = 0; index[1] = 0;
lon1 = 40; lon1 = 40;
lon2 = size - 40; lon2 = size - 40;
lat1 = 40; lat1 = 40;
lat2 = size - 40; lat2 = size - 40;
mCoords[10] = lon1; points[10] = lon1;
mCoords[11] = lat1; points[11] = lat1;
mCoords[12] = lon2; points[12] = lon2;
mCoords[13] = lat1; points[13] = lat1;
mCoords[14] = lon2; points[14] = lon2;
mCoords[15] = lat2; points[15] = lat2;
mCoords[16] = lon1; points[16] = lon1;
mCoords[17] = lat2; points[17] = lat2;
mCoords[18] = lon1; points[18] = lon1;
mCoords[19] = lat1; points[19] = lat1;
mIndex[2] = 10; index[2] = 10;
mIndex[3] = 0; index[3] = 0;
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, mIndex, true, 0); mapDatabaseCallback.renderWay((byte) 0, mTags, mGeom, true, 0);
mIndex[0] = 4; index[0] = 4;
mIndex[1] = -1; index[1] = -1;
// middle horizontal // middle horizontal
mCoords[0] = 0; points[0] = 0;
mCoords[1] = size / 2; points[1] = size / 2;
mCoords[2] = size; points[2] = size;
mCoords[3] = size / 2; points[3] = size / 2;
Tag[] tags = new Tag[2]; mapDatabaseCallback.renderWay((byte) 0, mTagsWay, mGeom, false, 0);
tags[0] = mTagsWay[0];
tags[1] = mTagsWay[1];
mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex, false, 0);
// center up // center up
mCoords[0] = size / 2; points[0] = size / 2;
mCoords[1] = -size / 2; points[1] = -size / 2;
mCoords[2] = size / 2; points[2] = size / 2;
mCoords[3] = size / 2; points[3] = size / 2;
tags = new Tag[2]; mapDatabaseCallback.renderWay((byte) 0, mTagsWay, mGeom,
tags[0] = mTagsWay[0];
tags[1] = mTagsWay[1];
mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex,
false, 0); false, 0);
// center down // center down
mCoords[0] = size / 2; points[0] = size / 2;
mCoords[1] = size / 2; points[1] = size / 2;
mCoords[2] = size / 2; points[2] = size / 2;
mCoords[3] = size / 2 + size; points[3] = size / 2 + size;
tags = new Tag[2]; mapDatabaseCallback.renderWay((byte) 0, mTagsWay, mGeom, false, 0);
tags[0] = mTagsWay[0];
tags[1] = mTagsWay[1];
mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex, false, 0);
// left-top to center // left-top to center
mCoords[0] = size / 2; points[0] = size / 2;
mCoords[1] = size / 2; points[1] = size / 2;
mCoords[2] = 10; points[2] = 10;
mCoords[3] = 10; points[3] = 10;
tags = new Tag[2]; mapDatabaseCallback.renderWay((byte) 1, mTagsWay, mGeom, false, 0);
tags[0] = mTagsWay[0];
tags[1] = mTagsWay[1];
mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false, 0);
// middle horizontal // middle horizontal
mCoords[0] = 0; points[0] = 0;
mCoords[1] = 10; points[1] = 10;
mCoords[2] = size; points[2] = size;
mCoords[3] = 10; points[3] = 10;
tags = new Tag[2]; mapDatabaseCallback.renderWay((byte) 1, mTagsWay, mGeom, false, 0);
tags[0] = mTagsWay[0];
tags[1] = mTagsWay[1];
mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false, 0);
// middle horizontal // middle horizontal
mCoords[0] = 10; points[0] = 10;
mCoords[1] = 0; points[1] = 0;
mCoords[2] = 10; points[2] = 10;
mCoords[3] = size; points[3] = size;
tags = new Tag[2]; mapDatabaseCallback.renderWay((byte) 1, mTagsWay, mGeom, false, 0);
tags[0] = mTagsWay[0];
tags[1] = mTagsWay[1];
mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false, 0);
// lon1 = size / 2; // lon1 = size / 2;
// lat1 = size / 2; // lat1 = size / 2;

View File

@ -18,6 +18,7 @@ import static org.oscim.generator.JobTile.STATE_NONE;
import java.util.Arrays; import java.util.Arrays;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.MercatorProjection; import org.oscim.core.MercatorProjection;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.Tile; import org.oscim.core.Tile;
@ -70,9 +71,14 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
private static final Tag[] debugTagWay = { new Tag("debug", "way") }; private static final Tag[] debugTagWay = { new Tag("debug", "way") };
private static final Tag[] debugTagArea = { new Tag("debug", "area") }; private static final Tag[] debugTagArea = { new Tag("debug", "area") };
private final float[] debugBoxCoords = { 0, 0, 0, Tile.TILE_SIZE, private final GeometryBuffer mDebugPoint = new GeometryBuffer(
Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE, 0, 0, 0 }; new float[] { Tile.TILE_SIZE >> 1, 10 },
private final short[] debugBoxIndex = { 10 }; new short[] { 2 });
private final GeometryBuffer mDebugBox = new GeometryBuffer(
new float[] { 0, 0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE,
Tile.TILE_SIZE, Tile.TILE_SIZE, 0, 0, 0 },
new short[] { 10 });
private static RenderTheme renderTheme; private static RenderTheme renderTheme;
private static int renderLevels; private static int renderLevels;
@ -84,13 +90,10 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
// currently processed tile // currently processed tile
private MapTile mTile; private MapTile mTile;
// coordinates of the currently processed way // currently processed geometry
private float[] mCoords; private GeometryBuffer mGeom;
private short[] mIndices;
private boolean mClosed; private boolean mClosed;
private float mPoiX, mPoiY;
private int mPriority; private int mPriority;
// current line layer, will be added to outline layers // current line layer, will be added to outline layers
@ -107,9 +110,6 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
private Tag mTagName; private Tag mTagName;
private Tag mTagHouseNr; private Tag mTagHouseNr;
private boolean mDebugDrawPolygons;
boolean mDebugDrawUnmatched;
private final LineClipper mClipper; private final LineClipper mClipper;
public static void setRenderTheme(RenderTheme theme) { public static void setRenderTheme(RenderTheme theme) {
@ -131,65 +131,58 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
} }
public boolean executeJob(JobTile jobTile) { public boolean executeJob(JobTile jobTile) {
MapTile tile;
if (mMapDatabase == null) if (mMapDatabase == null)
return false; return false;
tile = mTile = (MapTile) jobTile; mTile = (MapTile) jobTile;
mDebugDrawPolygons = !debug.disablePolygons; if (mTile.layers != null) {
mDebugDrawUnmatched = debug.debugTheme;
if (tile.layers != null) {
// should be fixed now. // should be fixed now.
Log.d(TAG, "BUG tile already loaded " + tile + " " + tile.state); Log.d(TAG, "BUG tile already loaded " + mTile + " " + mTile.state);
mTile = null;
return false; return false;
} }
setScaleStrokeWidth(tile.zoomLevel); setScaleStrokeWidth(mTile.zoomLevel);
// account for area changes with latitude // account for area changes with latitude
mLatScaleFactor = 0.5f + 0.5f * ( mLatScaleFactor = 0.5f + 0.5f * ((float) Math.sin(Math.abs(MercatorProjection
(float) Math.sin(Math.abs(MercatorProjection .pixelYToLatitude(mTile.pixelY, mTile.zoomLevel)) * (Math.PI / 180)));
.pixelYToLatitude(tile.pixelY, tile.zoomLevel)) * (Math.PI / 180)));
mTile.layers = new Layers();
// query database, which calls renderWay and renderPOI
// callbacks while processing map tile data.
if (mMapDatabase.executeQuery(mTile, this) != QueryResult.SUCCESS) {
tile.layers = new Layers();
if (mMapDatabase.executeQuery(tile, this) != QueryResult.SUCCESS) {
//Log.d(TAG, "Failed loading: " + tile); //Log.d(TAG, "Failed loading: " + tile);
tile.layers.clear(); mTile.layers.clear();
tile.layers = null; mTile.layers = null;
TextItem.release(tile.labels); TextItem.release(mTile.labels);
tile.labels = null; mTile.labels = null;
// FIXME add STATE_FAILED? // FIXME add STATE_FAILED?
tile.state = STATE_NONE; mTile.state = STATE_NONE;
mTile = null;
return false; return false;
} }
if (debug.drawTileFrames) { if (debug.drawTileFrames) {
// draw tile coordinate // draw tile coordinate
mTagName = new Tag("name", tile.toString(), false); mTagName = new Tag("name", mTile.toString(), false);
mPoiX = Tile.TILE_SIZE >> 1; mGeom = mDebugPoint;
mPoiY = 10;
RenderInstruction[] ri; RenderInstruction[] ri;
ri = renderTheme.matchNode(debugTagWay, (byte) 0); ri = renderTheme.matchNode(debugTagWay, (byte) 0);
renderNode(ri, debugTagWay); renderNode(ri, debugTagWay);
// draw tile box // draw tile box
mIndices = debugBoxIndex; mGeom = mDebugBox;
if (MapView.enableClosePolygons) mGeom.index[0] = (short) (MapView.enableClosePolygons ? 8 : 10);
mIndices[0] = 8;
else
mIndices[0] = 10;
mCoords = debugBoxCoords;
mDrawingLayer = 10 * renderLevels; mDrawingLayer = 10 * renderLevels;
ri = renderTheme.matchWay(debugTagBox, (byte) 0, false); ri = renderTheme.matchWay(debugTagBox, (byte) 0, false);
renderWay(ri, debugTagBox); renderWay(ri, debugTagBox);
} }
mTile = null;
return true; return true;
} }
@ -265,65 +258,60 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
// ---------------- MapDatabaseCallback ----------------- // ---------------- MapDatabaseCallback -----------------
@Override @Override
public void renderPointOfInterest(byte layer, Tag[] tags, public void renderPOI(byte layer, Tag[] tags, GeometryBuffer geom) {
float latitude, float longitude) {
// reset state clearState();
mTagName = null;
mTagHouseNr = null;
mPoiX = longitude;
mPoiY = latitude;
// remove tags that should not be cached in Rendertheme // remove tags that should not be cached in Rendertheme
filterTags(tags); filterTags(tags);
// get render instructions
RenderInstruction[] ri = renderTheme.matchNode(tags, mTile.zoomLevel); RenderInstruction[] ri = renderTheme.matchNode(tags, mTile.zoomLevel);
if (ri == null) if (ri == null)
return; return;
mGeom = geom;
renderNode(ri, tags); renderNode(ri, tags);
} }
@Override @Override
public void renderWay(byte layer, Tag[] tags, float[] coords, short[] indices, public void renderWay(byte layer, Tag[] tags, GeometryBuffer geom,
boolean closed, int prio) { boolean closed, int prio) {
// reset state clearState();
mTagName = null;
mTagHouseNr = null;
mCurLineLayer = null;
// replace tags that should not be cached in Rendertheme (e.g. name) // replace tags that should not be cached in Rendertheme (e.g. name)
if (!filterTags(tags)) if (!filterTags(tags))
return; return;
mPriority = prio;
mClosed = closed;
mDrawingLayer = getValidLayer(layer) * renderLevels; mDrawingLayer = getValidLayer(layer) * renderLevels;
mCoords = coords;
mIndices = indices;
// get render instructions
RenderInstruction[] ri = renderTheme.matchWay(tags, RenderInstruction[] ri = renderTheme.matchWay(tags,
(byte) (mTile.zoomLevel + 0), closed); (byte) (mTile.zoomLevel + 0), closed);
mPriority = prio;
mClosed = closed;
mGeom = geom;
renderWay(ri, tags); renderWay(ri, tags);
if (mDebugDrawUnmatched && ri == null) if (debug.debugTheme && ri == null)
debugUnmatched(closed, tags); debugUnmatched(closed, tags);
mCurLineLayer = null; mCurLineLayer = null;
} }
private void debugUnmatched(boolean closed, Tag[] tags) { private void debugUnmatched(boolean closed, Tag[] tags) {
Log.d(TAG, "DBG way not matched: " + closed + " " + Arrays.deepToString(tags)); Log.d(TAG, "DBG way not matched: " + closed + " "
+ Arrays.deepToString(tags));
mTagName = new Tag("name", tags[0].key + ":" + tags[0].value, false); mTagName = new Tag("name", tags[0].key + ":"
+ tags[0].value, false);
RenderInstruction[] ri; RenderInstruction[] ri;
ri = renderTheme.matchWay(closed ? debugTagArea : debugTagWay, (byte) 0, true); ri = renderTheme.matchWay(closed ? debugTagArea : debugTagWay,
(byte) 0, true);
renderWay(ri, tags); renderWay(ri, tags);
} }
@ -344,6 +332,12 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
ri[i].renderNode(this, tags); ri[i].renderNode(this, tags);
} }
private void clearState() {
mTagName = null;
mTagHouseNr = null;
mCurLineLayer = null;
}
@Override @Override
public void renderWaterBackground() { public void renderWaterBackground() {
} }
@ -351,13 +345,10 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
// ----------------- RenderThemeCallback ----------------- // ----------------- RenderThemeCallback -----------------
@Override @Override
public void renderWay(Line line, int level) { public void renderWay(Line line, int level) {
// TODO projectToTile();
int numLayer = (mDrawingLayer * 2) + level; int numLayer = (mDrawingLayer * 2) + level;
if (line.stipple == 0) { if (line.stipple == 0) {
if (line.outline && mCurLineLayer == null) { if (line.outline && mCurLineLayer == null) {
// FIXME in RenderTheme
Log.e(TAG, "BUG in theme: line must come before outline!"); Log.e(TAG, "BUG in theme: line must come before outline!");
return; return;
} }
@ -384,8 +375,11 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
return; return;
} }
lineLayer.addLine(mCoords, mIndices, mClosed); lineLayer.addLine(mGeom.points, mGeom.index, mClosed);
// keep reference for outline layer
mCurLineLayer = lineLayer; mCurLineLayer = lineLayer;
} else { } else {
LineTexLayer lineLayer = (LineTexLayer) LineTexLayer lineLayer = (LineTexLayer)
mTile.layers.getLayer(numLayer, Layer.TEXLINE); mTile.layers.getLayer(numLayer, Layer.TEXLINE);
@ -404,7 +398,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
lineLayer.width = w; lineLayer.width = w;
} }
lineLayer.addLine(mCoords, mIndices); lineLayer.addLine(mGeom.points, mGeom.index);
} }
} }
@ -417,83 +411,82 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
if (mTile.layers.extrusionLayers == null) if (mTile.layers.extrusionLayers == null)
mTile.layers.extrusionLayers = new ExtrusionLayer(0); mTile.layers.extrusionLayers = new ExtrusionLayer(0);
((ExtrusionLayer) mTile.layers.extrusionLayers).addBuildings(mCoords, mIndices, ((ExtrusionLayer) mTile.layers.extrusionLayers)
mPriority); .addBuildings(mGeom.points, mGeom.index, mPriority);
return; return;
} }
if (!mDebugDrawPolygons) if (debug.disablePolygons)
return; return;
// if (!mProjected && !projectToTile()) PolygonLayer layer = (PolygonLayer)
// return; mTile.layers.getLayer(numLayer, Layer.POLYGON);
PolygonLayer layer = (PolygonLayer) mTile.layers.getLayer(numLayer, Layer.POLYGON);
if (layer == null) if (layer == null)
return; return;
if (layer.area == null) if (layer.area == null)
layer.area = area; layer.area = area;
layer.addPolygon(mCoords, mIndices); layer.addPolygon(mGeom.points, mGeom.index);
}
private String textValueForKey(Text text) {
String value = null;
if (text.textKey == Tag.TAG_KEY_NAME) {
if (mTagName != null)
value = mTagName.value;
} else if (text.textKey == Tag.TAG_KEY_HOUSE_NUMBER) {
if (mTagHouseNr != null)
value = mTagHouseNr.value;
}
return value;
} }
@Override @Override
public void renderAreaCaption(Text text) { public void renderAreaCaption(Text text) {
// Log.d(TAG, "renderAreaCaption: " + mTagName); // TODO place somewhere on polygon
if (text.textKey == Tag.TAG_KEY_NAME) { String value = textValueForKey(text);
if (mTagName == null) if (value == null)
return; return;
TextItem t = TextItem.get().set(mCoords[0], mCoords[1], mTagName.value, text); float x = mGeom.points[0];
t.next = mTile.labels; float y = mGeom.points[1];
mTile.labels = t;
}
else if (text.textKey == Tag.TAG_KEY_HOUSE_NUMBER) {
if (mTagHouseNr == null)
return;
TextItem t = TextItem.get().set(mCoords[0], mCoords[1], mTagHouseNr.value, text); mTile.addLabel(TextItem.get().set(x, y, value, text));
t.next = mTile.labels;
mTile.labels = t;
}
} }
@Override @Override
public void renderPointOfInterestCaption(Text text) { public void renderPointOfInterestCaption(Text text) {
// Log.d(TAG, "renderPointOfInterestCaption: " + mPoiX + " " + mPoiY + String value = textValueForKey(text);
// " " + mTagName); if (value == null)
if (mTagName == null)
return; return;
if (text.textKey == mTagEmptyName.key) { for (int i = 0, n = mGeom.index[0]; i < n; i += 2) {
TextItem t = TextItem.get().set(mPoiX, mPoiY, mTagName.value, text); float x = mGeom.points[i];
// TextItem t = new TextItem(mPoiX, mPoiY, mTagName.value, text); float y = mGeom.points[i + 1];
t.next = mTile.labels; mTile.addLabel(TextItem.get().set(x, y, value, text));
mTile.labels = t;
} }
} }
@Override @Override
public void renderWayText(Text text) { public void renderWayText(Text text) {
// Log.d(TAG, "renderWayText: " + mTagName); String value = textValueForKey(text);
if (value == null)
if (mTagName == null)
return; return;
if (text.textKey == mTagEmptyName.key && mTagName.value != null) { int offset = 0;
int offset = 0; for (int i = 0, n = mGeom.index.length; i < n; i++) {
for (int i = 0, n = mIndices.length; i < n; i++) { int length = mGeom.index[i];
int length = mIndices[i]; if (length < 4)
if (length < 4) break;
break;
mTile.labels = WayDecorator.renderText(mClipper, mCoords, mTagName.value, text, WayDecorator.renderText(mClipper, mGeom.points, value, text,
offset, length, mTile.labels); offset, length, mTile);
offset += length; offset += length;
}
} }
} }

View File

@ -16,6 +16,7 @@
package org.oscim.generator; package org.oscim.generator;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.renderer.MapTile;
import org.oscim.renderer.layer.TextItem; import org.oscim.renderer.layer.TextItem;
import org.oscim.theme.renderinstruction.Text; import org.oscim.theme.renderinstruction.Text;
import org.oscim.utils.GeometryUtils; import org.oscim.utils.GeometryUtils;
@ -23,10 +24,9 @@ import org.oscim.utils.LineClipper;
public final class WayDecorator { public final class WayDecorator {
public static TextItem renderText(LineClipper clipper, float[] coordinates, String string, public static void renderText(LineClipper clipper, float[] coordinates, String string,
Text text, Text text, int pos, int len, MapTile tile) {
int pos, int len, TextItem textItems) { //TextItem items = textItems;
TextItem items = textItems;
TextItem t = null; TextItem t = null;
// calculate the way name length plus some margin of safety // calculate the way name length plus some margin of safety
@ -214,12 +214,10 @@ public final class WayDecorator {
t.y2 = y2; t.y2 = y2;
t.length = (short) segmentLength; t.length = (short) segmentLength;
t.edges = edge; t.edges = edge;
t.next = items; tile.addLabel(t);
items = t;
i = last; i = last;
} }
return items;
} }
private WayDecorator() { private WayDecorator() {

View File

@ -126,4 +126,9 @@ public final class MapTile extends JobTile {
} }
proxies = 0; proxies = 0;
} }
public void addLabel(TextItem t){
t.next = labels;
labels = t;
}
} }

View File

@ -28,6 +28,7 @@ package org.oscim.renderer.overlays;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.generator.JobTile;
import org.oscim.renderer.BufferObject; import org.oscim.renderer.BufferObject;
import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.renderer.GLRenderer.Matrices;
@ -395,6 +396,8 @@ public class TextOverlay extends BasicOverlay {
for (int i = 0, n = mTileSet.cnt; i < n; i++) { for (int i = 0, n = mTileSet.cnt; i < n; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
if (t.state != JobTile.STATE_READY)
continue;
float dx = (float) (t.pixelX - pos.x); float dx = (float) (t.pixelX - pos.x);
float dy = (float) (t.pixelY - pos.y); float dy = (float) (t.pixelY - pos.y);
@ -459,8 +462,9 @@ public class TextOverlay extends BasicOverlay {
/* add caption */ /* add caption */
for (int i = 0, n = mTileSet.cnt; i < n; i++) { for (int i = 0, n = mTileSet.cnt; i < n; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
if (t.state != JobTile.STATE_READY)
continue;
float dx = (float) (t.pixelX - pos.x); float dx = (float) (t.pixelX - pos.x);
float dy = (float) (t.pixelY - pos.y); float dy = (float) (t.pixelY - pos.y);

View File

@ -63,11 +63,6 @@ class MatchingCacheKey {
MatchingCacheKey other = (MatchingCacheKey) obj; MatchingCacheKey other = (MatchingCacheKey) obj;
// if (mTags == null) {
// return (other.mTags == null);
// } else if (other.mTags == null)
// return false;
int length = mTags.length; int length = mTags.length;
if (length != other.mTags.length) if (length != other.mTags.length)
return false; return false;