From 8c8750a83380e5991d67ba3d933c4dca0d5b2aed Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Tue, 19 Mar 2013 00:40:12 +0100 Subject: [PATCH] add GeometryBuffer class to pass data from MapDatabase to TileGenerator --- src/org/oscim/core/GeometryBuffer.java | 42 ++++ .../oscim/database/IMapDatabaseCallback.java | 5 +- .../oscim/database/mapfile/MapDatabase.java | 67 +++--- .../oscim/database/oscimap/MapDatabase.java | 90 +++---- src/org/oscim/database/pbmap/MapDatabase.java | 176 +++----------- .../oscim/database/postgis/MapDatabase.java | 54 ++--- src/org/oscim/database/test/MapDatabase.java | 148 ++++++------ src/org/oscim/generator/TileGenerator.java | 219 +++++++++--------- src/org/oscim/generator/WayDecorator.java | 12 +- src/org/oscim/renderer/MapTile.java | 5 + .../oscim/renderer/overlays/TextOverlay.java | 6 +- src/org/oscim/theme/MatchingCacheKey.java | 5 - 12 files changed, 380 insertions(+), 449 deletions(-) create mode 100644 src/org/oscim/core/GeometryBuffer.java diff --git a/src/org/oscim/core/GeometryBuffer.java b/src/org/oscim/core/GeometryBuffer.java new file mode 100644 index 00000000..782183b4 --- /dev/null +++ b/src/org/oscim/core/GeometryBuffer.java @@ -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; + } +} diff --git a/src/org/oscim/database/IMapDatabaseCallback.java b/src/org/oscim/database/IMapDatabaseCallback.java index 67fde9d7..1dc108c2 100644 --- a/src/org/oscim/database/IMapDatabaseCallback.java +++ b/src/org/oscim/database/IMapDatabaseCallback.java @@ -14,6 +14,7 @@ */ package org.oscim.database; +import org.oscim.core.GeometryBuffer; import org.oscim.core.Tag; import org.oscim.database.mapfile.MapDatabase; @@ -36,7 +37,7 @@ public interface IMapDatabaseCallback { * @param longitude * 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. @@ -59,7 +60,7 @@ public interface IMapDatabaseCallback { * wheter the way is an polygon. * @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); // /** diff --git a/src/org/oscim/database/mapfile/MapDatabase.java b/src/org/oscim/database/mapfile/MapDatabase.java index 0f497f76..05f077d0 100644 --- a/src/org/oscim/database/mapfile/MapDatabase.java +++ b/src/org/oscim/database/mapfile/MapDatabase.java @@ -18,6 +18,7 @@ import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; +import org.oscim.core.GeometryBuffer; import org.oscim.core.MercatorProjection; import org.oscim.core.Tag; import org.oscim.core.Tile; @@ -197,8 +198,7 @@ public class MapDatabase implements IMapDatabase { private int mTileLongitude; private int[] mIntBuffer; - private final float[] mWayNodes = new float[100000]; - private int mWayNodePosition; + private final GeometryBuffer mGeom = new GeometryBuffer(1 << 14, 1 << 8); private int minLat, minLon; private Tile mTile; @@ -219,8 +219,6 @@ public class MapDatabase implements IMapDatabase { if (mIntBuffer == null) mIntBuffer = new int[MAXIMUM_WAY_NODES_SEQUENCE_LENGTH * 2]; - mWayNodePosition = 0; - try { mTile = tile; @@ -669,24 +667,30 @@ public class MapDatabase implements IMapDatabase { double sinLat = Math.sin(latitude * PI180); 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; } - private short[] processWayDataBlock(boolean doubleDeltaEncoding) { + private boolean processWayDataBlock(boolean doubleDeltaEncoding) { // get and check the number of way coordinate blocks (VBE-U) int numBlocks = mReadBuffer.readUnsignedInt(); if (numBlocks < 1 || numBlocks > Short.MAX_VALUE) { 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 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) { Log.w(TAG, "invalid number of way nodes: " + numWayNodes); logDebugSignatures(); - return null; + return false; } // each way node consists of latitude and longitude @@ -710,16 +714,16 @@ public class MapDatabase implements IMapDatabase { wayLengths[coordinateBlock] = (short) len; } - return wayLengths; + return true; } private int decodeWayNodesDoubleDelta(int length) { int[] buffer = mIntBuffer; - float[] outBuffer = mWayNodes; 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) int wayNodeLatitude = mTileLatitude + buffer[0]; @@ -728,8 +732,8 @@ public class MapDatabase implements IMapDatabase { int wayNodeLongitude = mTileLongitude + buffer[1]; // store the first way node - outBuffer[floatPos++] = wayNodeLongitude; - outBuffer[floatPos++] = wayNodeLatitude; + outBuffer[pointPos++] = wayNodeLongitude; + outBuffer[pointPos++] = wayNodeLatitude; int singleDeltaLatitude = 0; int singleDeltaLongitude = 0; @@ -750,23 +754,23 @@ public class MapDatabase implements IMapDatabase { if (dLon > minLon || dLon < -minLon || dLat > minLat || dLat < -minLat || (pos == length - 2)) { - outBuffer[floatPos++] = nLon; - outBuffer[floatPos++] = nLat; + outBuffer[pointPos++] = nLon; + outBuffer[pointPos++] = nLat; cnt += 2; } } - mWayNodePosition = floatPos; + mGeom.pointPos = pointPos; return cnt; } private int decodeWayNodesSingleDelta(int length) { int[] buffer = mIntBuffer; - float[] outBuffer = mWayNodes; 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) int wayNodeLatitude = mTileLatitude + buffer[0]; @@ -775,8 +779,8 @@ public class MapDatabase implements IMapDatabase { int wayNodeLongitude = mTileLongitude + buffer[1]; // store the first way node - outBuffer[floatPos++] = wayNodeLongitude; - outBuffer[floatPos++] = wayNodeLatitude; + outBuffer[pointPos++] = wayNodeLongitude; + outBuffer[pointPos++] = wayNodeLatitude; 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 || (pos == length - 2)) { - outBuffer[floatPos++] = nLon; - outBuffer[floatPos++] = nLat; + outBuffer[pointPos++] = nLon; + outBuffer[pointPos++] = nLat; cnt += 2; } } - mWayNodePosition = floatPos; + mGeom.pointPos = pointPos; return cnt; } @@ -965,18 +969,17 @@ public class MapDatabase implements IMapDatabase { } for (int wayDataBlock = 0; wayDataBlock < wayDataBlocks; ++wayDataBlock) { - short[] wayLengths = processWayDataBlock(featureWayDoubleDeltaEncoding); - if (wayLengths == null) + if (!processWayDataBlock(featureWayDoubleDeltaEncoding)) return false; // wayDataContainer.textPos = textPos; - int l = wayLengths[0]; + int l = mGeom.index[0]; - boolean closed = mWayNodes[0] == mWayNodes[l - 2] - && mWayNodes[1] == mWayNodes[l - 1]; + boolean closed = mGeom.points[0] == mGeom.points[l - 2] + && mGeom.points[1] == mGeom.points[l - 1]; - projectToTile(mWayNodes, wayLengths); - mapDatabaseCallback.renderWay(layer, curTags, mWayNodes, wayLengths, closed, 0); + projectToTile(mGeom.points, mGeom.index); + mapDatabaseCallback.renderWay(layer, curTags, mGeom, closed, 0); } } diff --git a/src/org/oscim/database/oscimap/MapDatabase.java b/src/org/oscim/database/oscimap/MapDatabase.java index 17ce2c78..914d9eaa 100644 --- a/src/org/oscim/database/oscimap/MapDatabase.java +++ b/src/org/oscim/database/oscimap/MapDatabase.java @@ -23,6 +23,7 @@ import java.util.Arrays; import org.oscim.core.BoundingBox; import org.oscim.core.GeoPoint; +import org.oscim.core.GeometryBuffer; import org.oscim.core.Tag; import org.oscim.core.Tile; import org.oscim.database.IMapDatabase; @@ -207,7 +208,7 @@ public class MapDatabase implements IMapDatabase { } // /////////////// 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 private int mBytesProcessed; @@ -230,10 +231,11 @@ public class MapDatabase implements IMapDatabase { private static final int TAG_ELEM_PRIORITY = 31; private short[] mTmpKeys = new short[100]; - private short[] mIndices = new short[10]; 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; @@ -243,8 +245,6 @@ public class MapDatabase implements IMapDatabase { for (int i = 0; i < 10; i++) tags[i] = new Tag[i + 1]; mElementTags = tags; - - mTmpCoords = new float[MAX_WAY_COORDS]; } private boolean decode() throws IOException { @@ -309,25 +309,43 @@ public class MapDatabase implements IMapDatabase { return true; } - private boolean decodeTileElement(int type) throws IOException { - int bytes = decodeVarint32(); + private int decodeWayIndices(int indexCnt) throws IOException { + mGeom.index = decodeShortArray(indexCnt, mGeom.index); - int end = mBytesProcessed + bytes; - int indexCnt = 1; + short[] index = mGeom.index; 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; short[] index = null; + int end = mBytesProcessed + bytes; + int indexCnt = 1; + int layer = 5; + int prio = 0; + boolean skip = 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; + mGeom.index[0] = 2; + } while (mBytesProcessed < end) { // read tag and wire type @@ -347,16 +365,7 @@ public class MapDatabase implements IMapDatabase { break; case TAG_ELEM_INDEX: - mIndices = index = decodeShortArray(indexCnt, mIndices); - - 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; + coordCnt = decodeWayIndices(indexCnt); break; case TAG_ELEM_COORDS: @@ -387,20 +396,22 @@ public class MapDatabase implements IMapDatabase { if (fail || tags == null || indexCnt == 0) { 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") + " " + indexCnt + " " + coordCnt); return false; } - float[] coords = mTmpCoords; - - if (type == TAG_TILE_LINE) - mMapGenerator.renderWay((byte) layer, tags, coords, index, false, prio); - else if (type == TAG_TILE_POLY) - mMapGenerator.renderWay((byte) layer, tags, coords, index, true, prio); - else { - mMapGenerator.renderPointOfInterest((byte) layer, tags, coords[1], coords[0]); + switch (type) { + case TAG_TILE_LINE: + mMapGenerator.renderWay((byte) layer, tags, mGeom, false, prio); + break; + case TAG_TILE_POLY: + mMapGenerator.renderWay((byte) layer, tags, mGeom, true, prio); + break; + case TAG_TILE_POINT: + mMapGenerator.renderPOI((byte) layer, tags, mGeom); + break; } return true; @@ -463,7 +474,6 @@ public class MapDatabase implements IMapDatabase { int pos = lwHttp.bufferPos; int end = pos + bytes; - float[] coords = mTmpCoords; byte[] buf = lwHttp.buffer; int cnt = 0; int result; @@ -474,11 +484,13 @@ public class MapDatabase implements IMapDatabase { float scale = mScaleFactor; - if (nodes * 2 > coords.length) { - Log.d(TAG, mTile + " increase way coord buffer to " + (nodes * 2)); - float[] tmp = new float[nodes * 2]; - mTmpCoords = coords = tmp; - } + float[] coords = mGeom.ensurePointSize(nodes, false); + + // if (nodes * 2 > coords.length) { + // Log.d(TAG, mTile + " increase way coord buffer to " + (nodes * 2)); + // float[] tmp = new float[nodes * 2]; + // mTmpCoords = coords = tmp; + // } // read repeated sint32 while (pos < end) { diff --git a/src/org/oscim/database/pbmap/MapDatabase.java b/src/org/oscim/database/pbmap/MapDatabase.java index 26816fe7..97e343d0 100644 --- a/src/org/oscim/database/pbmap/MapDatabase.java +++ b/src/org/oscim/database/pbmap/MapDatabase.java @@ -36,6 +36,7 @@ import java.util.Map; import org.oscim.core.BoundingBox; import org.oscim.core.GeoPoint; +import org.oscim.core.GeometryBuffer; import org.oscim.core.Tag; import org.oscim.core.Tile; import org.oscim.database.IMapDatabase; @@ -89,9 +90,6 @@ public class MapDatabase implements IMapDatabase { private Tag[] curTags = new Tag[MAX_TILE_TAGS]; private int mCurTagCnt; - // private HttpClient mClient; - // private HttpGet mRequest = null; - private IMapDatabaseCallback mMapGenerator; private float mScaleFactor; private JobTile mTile; @@ -147,76 +145,13 @@ public class MapDatabase implements IMapDatabase { 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 { - // if (USE_LW_HTTP) { if (lwHttpSendRequest(tile) && lwHttpReadHeader() > 0) { cacheBegin(tile, f); decode(); } else { 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) { Log.d(TAG, "Socket exception: " + ex.getMessage()); result = QueryResult.FAILED; @@ -233,9 +168,6 @@ public class MapDatabase implements IMapDatabase { mLastRequest = SystemClock.elapsedRealtime(); - // if (USE_APACHE_HTTP) - // mRequest = null; - cacheFinish(tile, f, result == QueryResult.SUCCESS); return result; @@ -258,37 +190,9 @@ public class MapDatabase implements IMapDatabase { 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 public OpenResult open(MapOptions options) { - //if (USE_APACHE_HTTP) - // createClient(); - if (mOpenFile) return OpenResult.SUCCESS; @@ -344,15 +248,6 @@ public class MapDatabase implements IMapDatabase { @Override public void close() { mOpenFile = false; - // if (USE_APACHE_HTTP) { - // if (mClient != null) { - // mClient.getConnectionManager().shutdown(); - // mClient = null; - // } - // } - - // if (USE_LW_HTTP) { - mSockAddr = null; if (mSocket != null) { @@ -363,7 +258,7 @@ public class MapDatabase implements IMapDatabase { } mSocket = null; } - // } + if (USE_CACHE) { cacheDir = null; } @@ -384,17 +279,6 @@ public class MapDatabase implements IMapDatabase { } // /////////////// 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_WAYS = 2; 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_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 { mBytesProcessed = 0; int val; @@ -544,19 +442,16 @@ public class MapDatabase implements IMapDatabase { if (fail || index == null || tags == null || indexCnt == 0 || tagCnt == 0) { Log.d(TAG, "failed reading way: bytes:" + bytes + " index:" - + (index == null ? "null" : index.toString()) + " tag:" + (tags != null ? tags.toString() : "...") + " " + indexCnt + " " + coordCnt + " " + tagCnt); return false; } - float[] coords = tmpCoords; - // FIXME, remove all tiles from cache then remove this below if (layer == 0) layer = 5; - mMapGenerator.renderWay((byte) layer, tags, coords, index, polygon, 0); + mMapGenerator.renderWay((byte) layer, tags, mGeom, polygon, 0); return true; } @@ -621,22 +516,23 @@ public class MapDatabase implements IMapDatabase { // read repeated sint32 int lastX = 0; int lastY = 0; + float[] coords = mGeom.ensurePointSize(numNodes, false); + while (mBytesProcessed < end && cnt < numNodes) { int lon = decodeZigZag32(decodeVarint32()); int lat = decodeZigZag32(decodeVarint32()); lastX = lon + lastX; lastY = lat + lastY; - - mMapGenerator.renderPointOfInterest(layer, - tags, Tile.TILE_SIZE - lastY / scale, lastX / scale); - cnt += 2; + coords[cnt++] = lastX / scale; + coords[cnt++] = Tile.TILE_SIZE - lastY / scale; } + + mGeom.index[0] = (short)numNodes; + mMapGenerator.renderPOI(layer, tags, mGeom); + return cnt; } - private int MAX_WAY_COORDS = 32768; - - private float[] tmpCoords = new float[MAX_WAY_COORDS]; private Tag[] decodeWayTags(int tagCnt) throws IOException { int bytes = decodeVarint32(); @@ -676,15 +572,15 @@ public class MapDatabase implements IMapDatabase { return tags; } - private short[] mIndices = new short[10]; - private short[] decodeWayIndices(int indexCnt) throws IOException { int bytes = decodeVarint32(); - short[] index = mIndices; - if (index.length < indexCnt + 1) { - index = mIndices = new short[indexCnt + 1]; - } + short[] index = mGeom.ensureIndexSize(indexCnt, false); + +// mIndices; +// if (index.length < indexCnt + 1) { +// index = mIndices = new short[indexCnt + 1]; +// } readBuffer(bytes); @@ -762,22 +658,16 @@ public class MapDatabase implements IMapDatabase { int pos = mBufferPos; int end = pos + bytes; - float[] coords = tmpCoords; byte[] buf = mReadBuffer; int cnt = 0; int result; + float scale = mScaleFactor; int x, lastX = 0; int y, lastY = 0; boolean even = true; - float scale = mScaleFactor; - - 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; - } + float[] coords = mGeom.ensurePointSize(nodes, false); // read repeated sint32 while (pos < end) { diff --git a/src/org/oscim/database/postgis/MapDatabase.java b/src/org/oscim/database/postgis/MapDatabase.java index 561832e4..28bfdde7 100644 --- a/src/org/oscim/database/postgis/MapDatabase.java +++ b/src/org/oscim/database/postgis/MapDatabase.java @@ -25,6 +25,7 @@ import java.util.Properties; import org.oscim.core.BoundingBox; import org.oscim.core.GeoPoint; +import org.oscim.core.GeometryBuffer; import org.oscim.core.Tag; import org.oscim.core.WebMercator; import org.oscim.database.IMapDatabase; @@ -49,10 +50,11 @@ public class MapDatabase implements IMapDatabase { private final float mScale = 1; - private int mCoordPos = 0; - private int mIndexPos = 0; - private float[] mCoords; - private short[] mIndex; +// private int mCoordPos = 0; +// private int mIndexPos = 0; +// private float[] mCoords; +// private short[] mIndex; + private final GeometryBuffer mGeom = new GeometryBuffer(1 << 14, 1 << 8); private Tag[] mTags; @@ -128,8 +130,8 @@ public class MapDatabase implements IMapDatabase { // int cnt = 0; try { while (r != null && r.next()) { - mIndexPos = 0; - mCoordPos = 0; + mGeom.indexPos = 0; + mGeom.pointPos =0; // cnt++; try { Object obj = r.getObject(1); @@ -172,17 +174,20 @@ public class MapDatabase implements IMapDatabase { continue; boolean polygon = parse(b); - if (mIndexPos == 0) { + if (mGeom.indexPos == 0) { Log.d(TAG, "no index: skip way"); continue; - } else if (mIndexPos == 1) { - mapDatabaseCallback.renderPointOfInterest((byte) 0, mTags, - mCoords[1], mCoords[0]); + } else if (mGeom.indexPos == 1) { + mapDatabaseCallback.renderPOI((byte) 0, mTags, mGeom); } else { - short[] idx = new short[mIndexPos]; - System.arraycopy(mIndex, 0, idx, 0, mIndexPos); - mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, idx, polygon, 0); +// short[] idx = new short[mIndexPos]; +// System.arraycopy(mIndex, 0, idx, 0, mIndexPos); +// + if (mGeom.index.length > mGeom.indexPos) + mGeom.index[mGeom.indexPos] = -1; + + mapDatabaseCallback.renderWay((byte) 0, mTags, mGeom, polygon, 0); } } } catch (SQLException e) { @@ -212,10 +217,6 @@ public class MapDatabase implements IMapDatabase { @Override public OpenResult open(MapOptions options) { mOpenFile = true; - if (mCoords == null) { - mCoords = new float[100000]; - mIndex = new short[100000]; - } return OpenResult.SUCCESS; } @@ -230,8 +231,6 @@ public class MapDatabase implements IMapDatabase { connection = null; } } - mCoords = null; - mIndex = null; mOpenFile = false; } @@ -315,10 +314,11 @@ public class MapDatabase implements IMapDatabase { private void parsePoint(ValueGetter data, boolean haveZ, boolean haveM) { // double X = data.getDouble(); // double Y = data.getDouble(); - mCoords[0] = (float) (data.getDouble() * mScale); - mCoords[1] = (float) (data.getDouble() * mScale); - mIndex[0] = 2; - mIndexPos = 1; + mGeom.points[0] = (float) (data.getDouble() * mScale); + mGeom.points[1] = (float) (data.getDouble() * mScale); + mGeom.index[0] = 2; + mGeom.indexPos= 1; + if (haveZ) data.getDouble(); @@ -338,7 +338,7 @@ public class MapDatabase implements IMapDatabase { private void parseGeometryArray(ValueGetter data, int count) { for (int i = 0; i < count; i++) { 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) { int count = data.getInt(); for (int i = 0; i < count; i++) { - mCoords[mCoordPos++] = (float) (data.getDouble()) * mScale; - mCoords[mCoordPos++] = (float) (data.getDouble()) * mScale; + mGeom.points[mGeom.pointPos++] = (float) (data.getDouble()) * mScale; + mGeom.points[mGeom.pointPos++] = (float) (data.getDouble()) * mScale; if (haveZ) data.getDouble(); if (haveM) data.getDouble(); } - mIndex[mIndexPos++] = (short) (count * 2); + mGeom.index[mGeom.indexPos++] = (short) (count * 2); } private void parsePolygon(ValueGetter data, boolean haveZ, boolean haveM) { diff --git a/src/org/oscim/database/test/MapDatabase.java b/src/org/oscim/database/test/MapDatabase.java index 34f17342..5e120c71 100644 --- a/src/org/oscim/database/test/MapDatabase.java +++ b/src/org/oscim/database/test/MapDatabase.java @@ -15,6 +15,7 @@ package org.oscim.database.test; import org.oscim.core.BoundingBox; +import org.oscim.core.GeometryBuffer; import org.oscim.core.Tag; import org.oscim.core.Tile; import org.oscim.database.IMapDatabase; @@ -32,18 +33,21 @@ import org.oscim.generator.JobTile; public class MapDatabase implements IMapDatabase { private final static String PROJECTION = "Mercator"; - private float[] mCoords = new float[20]; - private short[] mIndex = new short[4]; + //private float[] mCoords = new float[20]; + //private short[] mIndex = new short[4]; + + GeometryBuffer mGeom = new GeometryBuffer(new float[20], new short[4]); + // private Tag[] mTags = { new Tag("boundary", "administrative"), new // Tag("admin_level", "2") }; - private Tag[] mTags = { new Tag("natural", "water") }; - private Tag[] mTagsWay = { new Tag("highway", "primary"), new Tag("name", "Highway Rd") }; + private final Tag[] mTags = { new Tag("natural", "water") }; + private final Tag[] mTagsWay = { new Tag("highway", "primary"), new Tag("name", "Highway Rd") }; // private Tag[] mNameTags; private final MapInfo mMapInfo = 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); private boolean mOpenFile = false; @@ -52,118 +56,102 @@ public class MapDatabase implements IMapDatabase { public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) { int size = Tile.TILE_SIZE; + float[] points = mGeom.points; + short[] index = mGeom.index; float lat1 = -1; float lon1 = -1; float lat2 = size + 1; float lon2 = size + 1; - mCoords[0] = lon1; - mCoords[1] = lat1; + points[0] = lon1; + points[1] = lat1; - mCoords[2] = lon2; - mCoords[3] = lat1; + points[2] = lon2; + points[3] = lat1; - mCoords[4] = lon2; - mCoords[5] = lat2; + points[4] = lon2; + points[5] = lat2; - mCoords[6] = lon1; - mCoords[7] = lat2; + points[6] = lon1; + points[7] = lat2; - mCoords[8] = lon1; - mCoords[9] = lat1; + points[8] = lon1; + points[9] = lat1; - mIndex[0] = 10; - mIndex[1] = 0; + index[0] = 10; + index[1] = 0; lon1 = 40; lon2 = size - 40; lat1 = 40; lat2 = size - 40; - mCoords[10] = lon1; - mCoords[11] = lat1; + points[10] = lon1; + points[11] = lat1; - mCoords[12] = lon2; - mCoords[13] = lat1; + points[12] = lon2; + points[13] = lat1; - mCoords[14] = lon2; - mCoords[15] = lat2; + points[14] = lon2; + points[15] = lat2; - mCoords[16] = lon1; - mCoords[17] = lat2; + points[16] = lon1; + points[17] = lat2; - mCoords[18] = lon1; - mCoords[19] = lat1; + points[18] = lon1; + points[19] = lat1; - mIndex[2] = 10; - mIndex[3] = 0; + index[2] = 10; + index[3] = 0; - mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, mIndex, true, 0); + mapDatabaseCallback.renderWay((byte) 0, mTags, mGeom, true, 0); - mIndex[0] = 4; - mIndex[1] = -1; + index[0] = 4; + index[1] = -1; // middle horizontal - mCoords[0] = 0; - mCoords[1] = size / 2; - mCoords[2] = size; - mCoords[3] = size / 2; - Tag[] tags = new Tag[2]; - tags[0] = mTagsWay[0]; - tags[1] = mTagsWay[1]; - mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex, false, 0); + points[0] = 0; + points[1] = size / 2; + points[2] = size; + points[3] = size / 2; + mapDatabaseCallback.renderWay((byte) 0, mTagsWay, mGeom, false, 0); // center up - mCoords[0] = size / 2; - mCoords[1] = -size / 2; - mCoords[2] = size / 2; - mCoords[3] = size / 2; - tags = new Tag[2]; - tags[0] = mTagsWay[0]; - tags[1] = mTagsWay[1]; - mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex, + points[0] = size / 2; + points[1] = -size / 2; + points[2] = size / 2; + points[3] = size / 2; + mapDatabaseCallback.renderWay((byte) 0, mTagsWay, mGeom, false, 0); // center down - mCoords[0] = size / 2; - mCoords[1] = size / 2; - mCoords[2] = size / 2; - mCoords[3] = size / 2 + size; - tags = new Tag[2]; - tags[0] = mTagsWay[0]; - tags[1] = mTagsWay[1]; - mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex, false, 0); + points[0] = size / 2; + points[1] = size / 2; + points[2] = size / 2; + points[3] = size / 2 + size; + mapDatabaseCallback.renderWay((byte) 0, mTagsWay, mGeom, false, 0); // left-top to center - mCoords[0] = size / 2; - mCoords[1] = size / 2; - mCoords[2] = 10; - mCoords[3] = 10; - tags = new Tag[2]; - tags[0] = mTagsWay[0]; - tags[1] = mTagsWay[1]; - mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false, 0); + points[0] = size / 2; + points[1] = size / 2; + points[2] = 10; + points[3] = 10; + mapDatabaseCallback.renderWay((byte) 1, mTagsWay, mGeom, false, 0); // middle horizontal - mCoords[0] = 0; - mCoords[1] = 10; - mCoords[2] = size; - mCoords[3] = 10; - tags = new Tag[2]; - tags[0] = mTagsWay[0]; - tags[1] = mTagsWay[1]; - mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false, 0); + points[0] = 0; + points[1] = 10; + points[2] = size; + points[3] = 10; + mapDatabaseCallback.renderWay((byte) 1, mTagsWay, mGeom, false, 0); // middle horizontal - mCoords[0] = 10; - mCoords[1] = 0; - mCoords[2] = 10; - mCoords[3] = size; - tags = new Tag[2]; - tags[0] = mTagsWay[0]; - tags[1] = mTagsWay[1]; - mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false, 0); + points[0] = 10; + points[1] = 0; + points[2] = 10; + points[3] = size; + mapDatabaseCallback.renderWay((byte) 1, mTagsWay, mGeom, false, 0); // lon1 = size / 2; // lat1 = size / 2; diff --git a/src/org/oscim/generator/TileGenerator.java b/src/org/oscim/generator/TileGenerator.java index af95db70..fd429374 100644 --- a/src/org/oscim/generator/TileGenerator.java +++ b/src/org/oscim/generator/TileGenerator.java @@ -18,6 +18,7 @@ import static org.oscim.generator.JobTile.STATE_NONE; import java.util.Arrays; +import org.oscim.core.GeometryBuffer; import org.oscim.core.MercatorProjection; import org.oscim.core.Tag; 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[] debugTagArea = { new Tag("debug", "area") }; - private final float[] debugBoxCoords = { 0, 0, 0, Tile.TILE_SIZE, - Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE, 0, 0, 0 }; - private final short[] debugBoxIndex = { 10 }; + private final GeometryBuffer mDebugPoint = new GeometryBuffer( + new float[] { Tile.TILE_SIZE >> 1, 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 int renderLevels; @@ -84,13 +90,10 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback { // currently processed tile private MapTile mTile; - // coordinates of the currently processed way - private float[] mCoords; - private short[] mIndices; - + // currently processed geometry + private GeometryBuffer mGeom; private boolean mClosed; - private float mPoiX, mPoiY; private int mPriority; // current line layer, will be added to outline layers @@ -107,9 +110,6 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback { private Tag mTagName; private Tag mTagHouseNr; - private boolean mDebugDrawPolygons; - boolean mDebugDrawUnmatched; - private final LineClipper mClipper; public static void setRenderTheme(RenderTheme theme) { @@ -131,65 +131,58 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback { } public boolean executeJob(JobTile jobTile) { - MapTile tile; if (mMapDatabase == null) return false; - tile = mTile = (MapTile) jobTile; + mTile = (MapTile) jobTile; - mDebugDrawPolygons = !debug.disablePolygons; - mDebugDrawUnmatched = debug.debugTheme; - - if (tile.layers != null) { + if (mTile.layers != null) { // 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; } - setScaleStrokeWidth(tile.zoomLevel); + setScaleStrokeWidth(mTile.zoomLevel); // account for area changes with latitude - mLatScaleFactor = 0.5f + 0.5f * ( - (float) Math.sin(Math.abs(MercatorProjection - .pixelYToLatitude(tile.pixelY, tile.zoomLevel)) * (Math.PI / 180))); + mLatScaleFactor = 0.5f + 0.5f * ((float) Math.sin(Math.abs(MercatorProjection + .pixelYToLatitude(mTile.pixelY, mTile.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); - tile.layers.clear(); - tile.layers = null; - TextItem.release(tile.labels); - tile.labels = null; - + mTile.layers.clear(); + mTile.layers = null; + TextItem.release(mTile.labels); + mTile.labels = null; // FIXME add STATE_FAILED? - tile.state = STATE_NONE; + mTile.state = STATE_NONE; + mTile = null; return false; } if (debug.drawTileFrames) { // draw tile coordinate - mTagName = new Tag("name", tile.toString(), false); - mPoiX = Tile.TILE_SIZE >> 1; - mPoiY = 10; - + mTagName = new Tag("name", mTile.toString(), false); + mGeom = mDebugPoint; RenderInstruction[] ri; ri = renderTheme.matchNode(debugTagWay, (byte) 0); renderNode(ri, debugTagWay); - // draw tile box - mIndices = debugBoxIndex; - if (MapView.enableClosePolygons) - mIndices[0] = 8; - else - mIndices[0] = 10; - - mCoords = debugBoxCoords; + mGeom = mDebugBox; + mGeom.index[0] = (short) (MapView.enableClosePolygons ? 8 : 10); mDrawingLayer = 10 * renderLevels; ri = renderTheme.matchWay(debugTagBox, (byte) 0, false); renderWay(ri, debugTagBox); } + mTile = null; return true; } @@ -265,65 +258,60 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback { // ---------------- MapDatabaseCallback ----------------- @Override - public void renderPointOfInterest(byte layer, Tag[] tags, - float latitude, float longitude) { + public void renderPOI(byte layer, Tag[] tags, GeometryBuffer geom) { - // reset state - mTagName = null; - mTagHouseNr = null; - - mPoiX = longitude; - mPoiY = latitude; + clearState(); // remove tags that should not be cached in Rendertheme filterTags(tags); + // get render instructions RenderInstruction[] ri = renderTheme.matchNode(tags, mTile.zoomLevel); if (ri == null) return; + mGeom = geom; renderNode(ri, tags); } @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) { - // reset state - mTagName = null; - mTagHouseNr = null; - mCurLineLayer = null; + clearState(); // replace tags that should not be cached in Rendertheme (e.g. name) if (!filterTags(tags)) return; - mPriority = prio; - mClosed = closed; - mDrawingLayer = getValidLayer(layer) * renderLevels; - mCoords = coords; - mIndices = indices; + // get render instructions RenderInstruction[] ri = renderTheme.matchWay(tags, (byte) (mTile.zoomLevel + 0), closed); + mPriority = prio; + mClosed = closed; + mGeom = geom; renderWay(ri, tags); - if (mDebugDrawUnmatched && ri == null) + if (debug.debugTheme && ri == null) debugUnmatched(closed, tags); mCurLineLayer = null; } 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; - ri = renderTheme.matchWay(closed ? debugTagArea : debugTagWay, (byte) 0, true); + ri = renderTheme.matchWay(closed ? debugTagArea : debugTagWay, + (byte) 0, true); renderWay(ri, tags); } @@ -344,6 +332,12 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback { ri[i].renderNode(this, tags); } + private void clearState() { + mTagName = null; + mTagHouseNr = null; + mCurLineLayer = null; + } + @Override public void renderWaterBackground() { } @@ -351,13 +345,10 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback { // ----------------- RenderThemeCallback ----------------- @Override public void renderWay(Line line, int level) { - // TODO projectToTile(); - int numLayer = (mDrawingLayer * 2) + level; if (line.stipple == 0) { if (line.outline && mCurLineLayer == null) { - // FIXME in RenderTheme Log.e(TAG, "BUG in theme: line must come before outline!"); return; } @@ -384,8 +375,11 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback { return; } - lineLayer.addLine(mCoords, mIndices, mClosed); + lineLayer.addLine(mGeom.points, mGeom.index, mClosed); + + // keep reference for outline layer mCurLineLayer = lineLayer; + } else { LineTexLayer lineLayer = (LineTexLayer) mTile.layers.getLayer(numLayer, Layer.TEXLINE); @@ -404,7 +398,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback { 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) mTile.layers.extrusionLayers = new ExtrusionLayer(0); - ((ExtrusionLayer) mTile.layers.extrusionLayers).addBuildings(mCoords, mIndices, - mPriority); + ((ExtrusionLayer) mTile.layers.extrusionLayers) + .addBuildings(mGeom.points, mGeom.index, mPriority); return; } - if (!mDebugDrawPolygons) + if (debug.disablePolygons) return; - // if (!mProjected && !projectToTile()) - // return; + PolygonLayer layer = (PolygonLayer) + mTile.layers.getLayer(numLayer, Layer.POLYGON); - PolygonLayer layer = (PolygonLayer) mTile.layers.getLayer(numLayer, Layer.POLYGON); if (layer == null) return; if (layer.area == null) 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 public void renderAreaCaption(Text text) { - // Log.d(TAG, "renderAreaCaption: " + mTagName); + // TODO place somewhere on polygon - if (text.textKey == Tag.TAG_KEY_NAME) { - if (mTagName == null) - return; + String value = textValueForKey(text); + if (value == null) + return; - TextItem t = TextItem.get().set(mCoords[0], mCoords[1], mTagName.value, text); - t.next = mTile.labels; - mTile.labels = t; - } - else if (text.textKey == Tag.TAG_KEY_HOUSE_NUMBER) { - if (mTagHouseNr == null) - return; + float x = mGeom.points[0]; + float y = mGeom.points[1]; - TextItem t = TextItem.get().set(mCoords[0], mCoords[1], mTagHouseNr.value, text); - t.next = mTile.labels; - mTile.labels = t; - } + mTile.addLabel(TextItem.get().set(x, y, value, text)); } @Override public void renderPointOfInterestCaption(Text text) { - // Log.d(TAG, "renderPointOfInterestCaption: " + mPoiX + " " + mPoiY + - // " " + mTagName); - - if (mTagName == null) + String value = textValueForKey(text); + if (value == null) return; - if (text.textKey == mTagEmptyName.key) { - TextItem t = TextItem.get().set(mPoiX, mPoiY, mTagName.value, text); - // TextItem t = new TextItem(mPoiX, mPoiY, mTagName.value, text); - t.next = mTile.labels; - mTile.labels = t; + for (int i = 0, n = mGeom.index[0]; i < n; i += 2) { + float x = mGeom.points[i]; + float y = mGeom.points[i + 1]; + mTile.addLabel(TextItem.get().set(x, y, value, text)); } } @Override public void renderWayText(Text text) { - // Log.d(TAG, "renderWayText: " + mTagName); - - if (mTagName == null) + String value = textValueForKey(text); + if (value == null) return; - if (text.textKey == mTagEmptyName.key && mTagName.value != null) { - int offset = 0; - for (int i = 0, n = mIndices.length; i < n; i++) { - int length = mIndices[i]; - if (length < 4) - break; - mTile.labels = WayDecorator.renderText(mClipper, mCoords, mTagName.value, text, - offset, length, mTile.labels); - offset += length; - } + int offset = 0; + for (int i = 0, n = mGeom.index.length; i < n; i++) { + int length = mGeom.index[i]; + if (length < 4) + break; + + WayDecorator.renderText(mClipper, mGeom.points, value, text, + offset, length, mTile); + offset += length; } } diff --git a/src/org/oscim/generator/WayDecorator.java b/src/org/oscim/generator/WayDecorator.java index 0dc96bca..073130db 100644 --- a/src/org/oscim/generator/WayDecorator.java +++ b/src/org/oscim/generator/WayDecorator.java @@ -16,6 +16,7 @@ package org.oscim.generator; import org.oscim.core.Tile; +import org.oscim.renderer.MapTile; import org.oscim.renderer.layer.TextItem; import org.oscim.theme.renderinstruction.Text; import org.oscim.utils.GeometryUtils; @@ -23,10 +24,9 @@ import org.oscim.utils.LineClipper; public final class WayDecorator { - public static TextItem renderText(LineClipper clipper, float[] coordinates, String string, - Text text, - int pos, int len, TextItem textItems) { - TextItem items = textItems; + public static void renderText(LineClipper clipper, float[] coordinates, String string, + Text text, int pos, int len, MapTile tile) { + //TextItem items = textItems; TextItem t = null; // calculate the way name length plus some margin of safety @@ -214,12 +214,10 @@ public final class WayDecorator { t.y2 = y2; t.length = (short) segmentLength; t.edges = edge; - t.next = items; - items = t; + tile.addLabel(t); i = last; } - return items; } private WayDecorator() { diff --git a/src/org/oscim/renderer/MapTile.java b/src/org/oscim/renderer/MapTile.java index 59e308a0..4ca462ea 100644 --- a/src/org/oscim/renderer/MapTile.java +++ b/src/org/oscim/renderer/MapTile.java @@ -126,4 +126,9 @@ public final class MapTile extends JobTile { } proxies = 0; } + + public void addLabel(TextItem t){ + t.next = labels; + labels = t; + } } diff --git a/src/org/oscim/renderer/overlays/TextOverlay.java b/src/org/oscim/renderer/overlays/TextOverlay.java index 82be3cbe..38246d95 100644 --- a/src/org/oscim/renderer/overlays/TextOverlay.java +++ b/src/org/oscim/renderer/overlays/TextOverlay.java @@ -28,6 +28,7 @@ package org.oscim.renderer.overlays; import org.oscim.core.MapPosition; import org.oscim.core.Tile; +import org.oscim.generator.JobTile; import org.oscim.renderer.BufferObject; import org.oscim.renderer.GLRenderer; 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++) { MapTile t = tiles[i]; + if (t.state != JobTile.STATE_READY) + continue; float dx = (float) (t.pixelX - pos.x); float dy = (float) (t.pixelY - pos.y); @@ -459,8 +462,9 @@ public class TextOverlay extends BasicOverlay { /* add caption */ for (int i = 0, n = mTileSet.cnt; i < n; i++) { - MapTile t = tiles[i]; + if (t.state != JobTile.STATE_READY) + continue; float dx = (float) (t.pixelX - pos.x); float dy = (float) (t.pixelY - pos.y); diff --git a/src/org/oscim/theme/MatchingCacheKey.java b/src/org/oscim/theme/MatchingCacheKey.java index a73d056a..29bb28ba 100644 --- a/src/org/oscim/theme/MatchingCacheKey.java +++ b/src/org/oscim/theme/MatchingCacheKey.java @@ -63,11 +63,6 @@ class MatchingCacheKey { MatchingCacheKey other = (MatchingCacheKey) obj; - // if (mTags == null) { - // return (other.mTags == null); - // } else if (other.mTags == null) - // return false; - int length = mTags.length; if (length != other.mTags.length) return false;