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;
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);
// /**

View File

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

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

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

View File

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

View File

@ -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() {

View File

@ -126,4 +126,9 @@ public final class MapTile extends JobTile {
}
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.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);

View File

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