use TagSet instead of Tag[] in MapElement

This commit is contained in:
Hannes Janetzek 2013-06-12 02:52:23 +02:00
parent 0ed0d1a154
commit 48369f6baf
11 changed files with 205 additions and 241 deletions

View File

@ -24,19 +24,12 @@ package org.oscim.core;
*/ */
public class MapElement extends GeometryBuffer { public class MapElement extends GeometryBuffer {
// osm layer of the way. // osm layer of the way.
public int layer; public int layer;
// osm tags of the way. // osm tags of the way.
public Tag[] tags; //public Tag[] tags;
public final TagSet tags = new TagSet();
// ---- random stuff, to be removed ----
// building tags
public int height;
public int minHeight;
public int priority;
public MapElement() { public MapElement() {
super(1024, 16); super(1024, 16);
@ -46,8 +39,18 @@ public class MapElement extends GeometryBuffer {
super(points, indices); super(points, indices);
} }
public void set(Tag[] tags, int layer) { public void setLayer(int layer) {
this.layer = layer; this.layer = layer;
this.tags = tags; //this.tags = tags;
} }
@Override
public void clear() {
super.clear();
}
// ---- random stuff, to be removed ----
// building tags
public int height;
public int minHeight;
public int priority;
} }

View File

@ -16,12 +16,11 @@ package org.oscim.layers.tile.vector;
import static org.oscim.layers.tile.MapTile.STATE_NONE; import static org.oscim.layers.tile.MapTile.STATE_NONE;
import java.util.Arrays;
import org.oscim.core.GeometryBuffer.GeometryType; import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.MapElement; import org.oscim.core.MapElement;
import org.oscim.core.MercatorProjection; import org.oscim.core.MercatorProjection;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.TagSet;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.layers.tile.MapTile; import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileLoader; import org.oscim.layers.tile.TileLoader;
@ -261,10 +260,11 @@ public class MapTileLoader extends TileLoader implements IRenderCallback, ITileD
// only with different name. // only with different name.
// Maybe this should be done within RenderTheme, also allowing // Maybe this should be done within RenderTheme, also allowing
// to set these replacement rules in theme file. // to set these replacement rules in theme file.
private boolean filterTags(Tag[] tags) { private boolean filterTags(TagSet in) {
mRenderBuildingModel = false; mRenderBuildingModel = false;
Tag[] tags = in.tags;
for (int i = 0; i < tags.length; i++) { for (int i = 0; i < in.numTags; i++) {
String key = tags[i].key; String key = tags[i].key;
if (tags[i].key == Tag.TAG_KEY_NAME) { if (tags[i].key == Tag.TAG_KEY_NAME) {
if (tags[i].value != null) { if (tags[i].value != null) {
@ -337,17 +337,16 @@ public class MapTileLoader extends TileLoader implements IRenderCallback, ITileD
mElement = null; mElement = null;
} }
private void debugUnmatched(boolean closed, Tag[] tags) { private void debugUnmatched(boolean closed, TagSet tags) {
Log.d(TAG, "DBG way not matched: " + closed + " " // Log.d(TAG, "DBG way not matched: " + closed + " "
+ Arrays.deepToString(tags)); // + Arrays.deepToString(tags));
//
mTagName = new Tag("name", tags[0].key + ":" // mTagName = new Tag("name", tags[0].key + ":"
+ tags[0].value, false); // + tags[0].value, false);
//
mElement.tags = closed ? debugTagArea : debugTagWay; // mElement.tags = closed ? debugTagArea : debugTagWay;
RenderInstruction[] ri = renderTheme.matchElement(mElement, mTile.zoomLevel); // RenderInstruction[] ri = renderTheme.matchElement(mElement, mTile.zoomLevel);
// renderWay(ri);
renderWay(ri);
} }
private void renderWay(RenderInstruction[] ri) { private void renderWay(RenderInstruction[] ri) {

View File

@ -15,6 +15,7 @@
package org.oscim.theme; package org.oscim.theme;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.TagSet;
class MatchingCacheKey { class MatchingCacheKey {
int mHash; int mHash;
@ -24,34 +25,38 @@ class MatchingCacheKey {
} }
MatchingCacheKey(MatchingCacheKey key) { MatchingCacheKey(MatchingCacheKey key) {
// need to clone tags as they belong to TileDataSource mTags = key.mTags;
mTags = key.mTags.clone();
mHash = key.mHash; mHash = key.mHash;
} }
// set temporary values for comparison // set temporary values for comparison
boolean set(Tag[] tags, MatchingCacheKey compare) { boolean set(TagSet tags, MatchingCacheKey compare) {
int length = tags.length; int numTags = tags.numTags;
if (compare != null && length == compare.mTags.length) { if (compare != null && numTags == compare.mTags.length) {
int i = 0; int i = 0;
for (; i < length; i++) { for (; i < numTags; i++) {
Tag t1 = tags[i]; Tag t1 = tags.tags[i];
Tag t2 = compare.mTags[i]; Tag t2 = compare.mTags[i];
if (!(t1 == t2 || (t1.key == t2.key && t1.value == t2.value))) if (!(t1 == t2 || (t1.key == t2.key && t1.value == t2.value)))
break; break;
} }
if (i == length) if (i == numTags)
return true; return true;
} }
// need to clone tags as they belong to TileDataSource
mTags = new Tag[numTags];
int result = 7; int result = 7;
for (int i = 0; i < length; i++) for (int i = 0; i < numTags; i++){
result = 31 * result + tags[i].hashCode(); Tag t = tags.tags[i];
result = 31 * result + t.hashCode();
mTags[i] = t;
}
mHash = 31 * result; mHash = 31 * result;
mTags = tags;
return false; return false;
} }

View File

@ -105,6 +105,9 @@ public class RenderTheme implements IRenderTheme {
cacheKey = new MatchingCacheKey(); cacheKey = new MatchingCacheKey();
matchType = type; matchType = type;
} }
RenderInstructionItem getRenderInstructions(){
return cache.get(cacheKey);
}
} }
class RenderInstructionItem { class RenderInstructionItem {
@ -200,7 +203,8 @@ public class RenderTheme implements IRenderTheme {
} }
if (ri == null) { if (ri == null) {
ris = cache.cache.get(cache.cacheKey); // get instruction for current cacheKey
ris = cache.getRenderInstructions();
for (ri = ris; ri != null; ri = ri.next) for (ri = ris; ri != null; ri = ri.next)
if ((ri.zoom & zoomMask) != 0) if ((ri.zoom & zoomMask) != 0)
@ -216,7 +220,7 @@ public class RenderTheme implements IRenderTheme {
matches.clear(); matches.clear();
for (Rule rule : mRules) for (Rule rule : mRules)
rule.matchElement(cache.matchType, element.tags, zoomMask, matches); rule.matchElement(cache.matchType, cache.cacheKey.mTags, zoomMask, matches);
int size = matches.size(); int size = matches.size();
if (size > 1) { if (size > 1) {
@ -225,7 +229,7 @@ public class RenderTheme implements IRenderTheme {
for (int j = i + 1; j < size; j++) { for (int j = i + 1; j < size; j++) {
if (matches.get(j) == r) { if (matches.get(j) == r) {
Log.d(TAG, "fix duplicate instruction! " Log.d(TAG, "fix duplicate instruction! "
+ Arrays.deepToString(element.tags) + Arrays.deepToString(cache.cacheKey.mTags)
+ ":" + zoomLevel); + ":" + zoomLevel);
matches.remove(j--); matches.remove(j--);
size--; size--;

View File

@ -471,8 +471,7 @@ public class MapDatabase implements ITileDataSource {
*/ */
private boolean processPOIs(ITileDataSink mapDataSink, int numberOfPois) { private boolean processPOIs(ITileDataSink mapDataSink, int numberOfPois) {
Tag[] poiTags = mTileSource.fileInfo.poiTags; Tag[] poiTags = mTileSource.fileInfo.poiTags;
Tag[] tags = null; int numTags = 0;
Tag[] curTags;
long x = mTile.tileX * Tile.SIZE; long x = mTile.tileX * Tile.SIZE;
long y = mTile.tileY * Tile.SIZE + Tile.SIZE; long y = mTile.tileY * Tile.SIZE + Tile.SIZE;
@ -510,13 +509,14 @@ public class MapDatabase implements ITileDataSource {
byte numberOfTags = (byte) (specialByte & POI_NUMBER_OF_TAGS_BITMASK); byte numberOfTags = (byte) (specialByte & POI_NUMBER_OF_TAGS_BITMASK);
if (numberOfTags != 0) { if (numberOfTags != 0) {
tags = mReadBuffer.readTags(poiTags, numberOfTags); if (!mReadBuffer.readTags(mElem.tags, poiTags, numberOfTags))
}
if (tags == null)
return false; return false;
curTags = tags; numTags = numberOfTags;
}
// reset to common tag position
mElem.tags.numTags = numTags;
// get the feature bitmask (1 byte) // get the feature bitmask (1 byte)
byte featureByte = mReadBuffer.readByte(); byte featureByte = mReadBuffer.readByte();
@ -525,10 +525,7 @@ public class MapDatabase implements ITileDataSource {
// check if the POI has a name // check if the POI has a name
if ((featureByte & POI_FEATURE_NAME) != 0) { if ((featureByte & POI_FEATURE_NAME) != 0) {
String str = mReadBuffer.readUTF8EncodedString(); String str = mReadBuffer.readUTF8EncodedString();
mElem.tags.add(new Tag(Tag.TAG_KEY_NAME, str, false));
curTags = new Tag[tags.length + 1];
System.arraycopy(tags, 0, curTags, 0, tags.length);
curTags[tags.length] = new Tag(Tag.TAG_KEY_NAME, str, false);
} }
// check if the POI has a house number // check if the POI has a house number
@ -551,18 +548,12 @@ public class MapDatabase implements ITileDataSource {
latitude = (int) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy); latitude = (int) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
mElem.clear(); mElem.clear();
mElem.startPoints(); mElem.startPoints();
mElem.addPoint(longitude, latitude); mElem.addPoint(longitude, latitude);
mElem.type = GeometryType.POINT; mElem.type = GeometryType.POINT;
mElem.set(curTags, layer); mElem.setLayer(layer);
mapDataSink.process(mElem); mapDataSink.process(mElem);
// mGeom.points[0] = longitude;
// mGeom.points[1] = latitude;
// mGeom.index[0] = 2;
// mapDatabaseCallback.renderPOI(layer, curTags, mGeom);
} }
return true; return true;
@ -715,9 +706,8 @@ public class MapDatabase implements ITileDataSource {
ITileDataSink mapDataSink, ITileDataSink mapDataSink,
int numberOfWays) { int numberOfWays) {
Tag[] tags = null;
Tag[] curTags;
Tag[] wayTags = mTileSource.fileInfo.wayTags; Tag[] wayTags = mTileSource.fileInfo.wayTags;
int numTags = 0;
int wayDataBlocks; int wayDataBlocks;
@ -757,11 +747,11 @@ public class MapDatabase implements ITileDataSource {
mReadBuffer.setBufferPosition(mReadBuffer.lastTagPosition); mReadBuffer.setBufferPosition(mReadBuffer.lastTagPosition);
byte numberOfTags = (byte) (mReadBuffer.readByte() & WAY_NUMBER_OF_TAGS_BITMASK); byte numberOfTags = (byte) (mReadBuffer.readByte() & WAY_NUMBER_OF_TAGS_BITMASK);
if (!mReadBuffer.readTags(mElem.tags, wayTags, numberOfTags))
tags = mReadBuffer.readTags(wayTags, numberOfTags);
if (tags == null)
return false; return false;
numTags = numberOfTags;
mReadBuffer.setBufferPosition(pos); mReadBuffer.setBufferPosition(pos);
} }
} else { } else {
@ -787,13 +777,13 @@ public class MapDatabase implements ITileDataSource {
// bit 5-8 represent the number of tag IDs // bit 5-8 represent the number of tag IDs
byte numberOfTags = (byte) (specialByte & WAY_NUMBER_OF_TAGS_BITMASK); byte numberOfTags = (byte) (specialByte & WAY_NUMBER_OF_TAGS_BITMASK);
if (numberOfTags != 0) if (numberOfTags != 0){
tags = mReadBuffer.readTags(wayTags, numberOfTags);
if (tags == null) if (!mReadBuffer.readTags(mElem.tags, wayTags, numberOfTags))
return false; return false;
curTags = tags; numTags = numberOfTags;
}
// get the feature bitmask (1 byte) // get the feature bitmask (1 byte)
byte featureByte = mReadBuffer.readByte(); byte featureByte = mReadBuffer.readByte();
@ -805,42 +795,36 @@ public class MapDatabase implements ITileDataSource {
boolean hasHouseNr = (featureByte & WAY_FEATURE_HOUSE_NUMBER) != 0; boolean hasHouseNr = (featureByte & WAY_FEATURE_HOUSE_NUMBER) != 0;
boolean hasRef = (featureByte & WAY_FEATURE_REF) != 0; boolean hasRef = (featureByte & WAY_FEATURE_REF) != 0;
int add = (hasName ? 1 : 0) + (hasHouseNr ? 1 : 0) + (hasRef ? 1 : 0); mElem.tags.numTags = numTags;
int addTag = tags.length;
if (add > 0) {
curTags = new Tag[tags.length + add];
System.arraycopy(tags, 0, curTags, 0, tags.length);
}
if (mTileSource.experimental) { if (mTileSource.experimental) {
if (hasName) { if (hasName) {
int textPos = mReadBuffer.readUnsignedInt(); int textPos = mReadBuffer.readUnsignedInt();
String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos); String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos);
curTags[addTag++] = new Tag(Tag.TAG_KEY_NAME, str, false); mElem.tags.add(new Tag(Tag.TAG_KEY_NAME, str, false));
} }
if (hasHouseNr) { if (hasHouseNr) {
int textPos = mReadBuffer.readUnsignedInt(); int textPos = mReadBuffer.readUnsignedInt();
String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos); String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos);
curTags[addTag++] = new Tag(Tag.TAG_KEY_HOUSE_NUMBER, str, false); mElem.tags.add(new Tag(Tag.TAG_KEY_HOUSE_NUMBER, str, false));
} }
if (hasRef) { if (hasRef) {
int textPos = mReadBuffer.readUnsignedInt(); int textPos = mReadBuffer.readUnsignedInt();
String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos); String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos);
curTags[addTag++] = new Tag(Tag.TAG_KEY_REF, str, false); mElem.tags.add(new Tag(Tag.TAG_KEY_REF, str, false));
} }
} else { } else {
if (hasName) { if (hasName) {
String str = mReadBuffer.readUTF8EncodedString(); String str = mReadBuffer.readUTF8EncodedString();
curTags[addTag++] = new Tag(Tag.TAG_KEY_NAME, str, false); mElem.tags.add(new Tag(Tag.TAG_KEY_NAME, str, false));
} }
if (hasHouseNr) { if (hasHouseNr) {
String str = mReadBuffer.readUTF8EncodedString(); String str = mReadBuffer.readUTF8EncodedString();
curTags[addTag++] = new Tag(Tag.TAG_KEY_HOUSE_NUMBER, str, false); mElem.tags.add(new Tag(Tag.TAG_KEY_HOUSE_NUMBER, str, false));
} }
if (hasRef) { if (hasRef) {
String str = mReadBuffer.readUTF8EncodedString(); String str = mReadBuffer.readUTF8EncodedString();
curTags[addTag++] = new Tag(Tag.TAG_KEY_REF, str, false); mElem.tags.add(new Tag(Tag.TAG_KEY_REF, str, false));
} }
} }
if ((featureByte & WAY_FEATURE_LABEL_POSITION) != 0) if ((featureByte & WAY_FEATURE_LABEL_POSITION) != 0)
@ -870,10 +854,9 @@ public class MapDatabase implements ITileDataSource {
&& mElem.points[1] == mElem.points[l - 1]; && mElem.points[1] == mElem.points[l - 1];
projectToTile(mElem.points, mElem.index); projectToTile(mElem.points, mElem.index);
mElem.layer = layer;
mElem.type = closed ? GeometryType.POLY : GeometryType.LINE; mElem.type = closed ? GeometryType.POLY : GeometryType.LINE;
mElem.set(curTags, layer); mElem.setLayer(layer);
mapDataSink.process(mElem); mapDataSink.process(mElem);
} }
@ -894,16 +877,6 @@ public class MapDatabase implements ITileDataSource {
return labelPosition; return labelPosition;
} }
// private int readOptionalWayDataBlocksByte(boolean
// featureWayDataBlocksByte) {
// if (featureWayDataBlocksByte) {
// // get and check the number of way data blocks (VBE-U)
// return mReadBuffer.readUnsignedInt();
// }
// // only one way data block exists
// return 1;
// }
private int[][] readZoomTable(SubFileParameter subFileParameter) { private int[][] readZoomTable(SubFileParameter subFileParameter) {
int rows = subFileParameter.zoomLevelMax - subFileParameter.zoomLevelMin + 1; int rows = subFileParameter.zoomLevelMax - subFileParameter.zoomLevelMin + 1;
int[][] zoomTable = new int[rows][2]; int[][] zoomTable = new int[rows][2];

View File

@ -20,6 +20,7 @@ import java.io.UnsupportedEncodingException;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.TagSet;
/** /**
* Reads from a {@link RandomAccessFile} into a buffer and decodes the data. * Reads from a {@link RandomAccessFile} into a buffer and decodes the data.
@ -400,8 +401,8 @@ public class ReadBuffer {
mBufferPosition += bytes; mBufferPosition += bytes;
} }
Tag[] readTags(Tag[] wayTags, byte numberOfTags) { boolean readTags(TagSet tags, Tag[] wayTags, byte numberOfTags) {
Tag[] tags = new Tag[numberOfTags]; tags.clear();
int maxTag = wayTags.length; int maxTag = wayTags.length;
@ -409,11 +410,11 @@ public class ReadBuffer {
int tagId = readUnsignedInt(); int tagId = readUnsignedInt();
if (tagId < 0 || tagId >= maxTag) { if (tagId < 0 || tagId >= maxTag) {
LOG.warning("invalid tag ID: " + tagId); LOG.warning("invalid tag ID: " + tagId);
return null; return true;
} }
tags[i] = wayTags[tagId]; tags.add(wayTags[tagId]);
} }
return tags; return true;
} }
private static final int WAY_NUMBER_OF_TAGS_BITMASK = 0x0f; private static final int WAY_NUMBER_OF_TAGS_BITMASK = 0x0f;

View File

@ -22,10 +22,9 @@ import java.util.ArrayList;
import org.oscim.core.GeometryBuffer.GeometryType; import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.MapElement; import org.oscim.core.MapElement;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.TagSet;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.tilesource.common.PbfDecoder;
import org.oscim.tilesource.ITileDataSink; import org.oscim.tilesource.ITileDataSink;
import org.oscim.tilesource.common.PbfDecoder;
import org.oscim.utils.pool.Inlist; import org.oscim.utils.pool.Inlist;
import org.oscim.utils.pool.Pool; import org.oscim.utils.pool.Pool;
@ -201,8 +200,8 @@ public class TileDecoder extends PbfDecoder {
if (f.elem.type == GeometryType.NONE) if (f.elem.type == GeometryType.NONE)
continue; continue;
mTagSet.clear(); f.elem.tags.clear();
mTagSet.add(layerTag); f.elem.tags.add(layerTag);
boolean hasName = false; boolean hasName = false;
String fallbackName = null; String fallbackName = null;
@ -223,19 +222,19 @@ public class TileDecoder extends PbfDecoder {
if (keyIdx == matchedLocal) { if (keyIdx == matchedLocal) {
hasName = true; hasName = true;
mTagSet.add(new Tag(Tag.TAG_KEY_NAME, val, false)); f.elem.tags.add(new Tag(Tag.TAG_KEY_NAME, val, false));
} else { } else {
key = keys.get(keyIdx); key = keys.get(keyIdx);
mTagSet.add(new Tag(key, val)); f.elem.tags.add(new Tag(key, val));
} }
} }
if (!hasName && fallbackName != null) if (!hasName && fallbackName != null)
mTagSet.add(new Tag(Tag.TAG_KEY_NAME, fallbackName, false)); f.elem.tags.add(new Tag(Tag.TAG_KEY_NAME, fallbackName, false));
// FIXME extract layer tag here // FIXME extract layer tag here
f.elem.set(mTagSet.asArray(), 5); f.elem.setLayer(5);
mMapDataCallback.process(f.elem); mMapDataCallback.process(f.elem);
mFeaturePool.release(f); mFeaturePool.release(f);
} }
@ -243,7 +242,6 @@ public class TileDecoder extends PbfDecoder {
return true; return true;
} }
private final TagSet mTagSet = new TagSet();
private final Pool<Feature> mFeaturePool = new Pool<Feature>() { private final Pool<Feature> mFeaturePool = new Pool<Feature>() {
int count; int count;
@ -260,7 +258,7 @@ public class TileDecoder extends PbfDecoder {
return false; return false;
} }
item.elem.tags = null; item.elem.tags.clear();
item.elem.clear(); item.elem.clear();
item.tags = null; item.tags = null;
item.type = 0; item.type = 0;
@ -339,9 +337,7 @@ public class TileDecoder extends PbfDecoder {
case TAG_FEATURE_TYPE: case TAG_FEATURE_TYPE:
type = decodeVarint32(); type = decodeVarint32();
//Log.d(TAG, "got type " + type); //Log.d(TAG, "got type " + type);
break; break;
case TAG_FEATURE_GEOMETRY: case TAG_FEATURE_GEOMETRY:

View File

@ -24,8 +24,8 @@ import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.MapElement; import org.oscim.core.MapElement;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.tilesource.common.PbfDecoder;
import org.oscim.tilesource.ITileDataSink; import org.oscim.tilesource.ITileDataSink;
import org.oscim.tilesource.common.PbfDecoder;
import android.util.Log; import android.util.Log;
@ -69,7 +69,6 @@ public class TileDecoder extends PbfDecoder {
public boolean decode(Tile tile, ITileDataSink sink, InputStream is, int contentLength) public boolean decode(Tile tile, ITileDataSink sink, InputStream is, int contentLength)
throws IOException { throws IOException {
setInputStream(is, contentLength); setInputStream(is, contentLength);
mTile = tile; mTile = tile;
@ -164,7 +163,6 @@ public class TileDecoder extends PbfDecoder {
int tagCnt = 0; int tagCnt = 0;
int coordCnt = 0; int coordCnt = 0;
int layer = 5; int layer = 5;
Tag[] tags = null;
boolean fail = false; boolean fail = false;
@ -178,11 +176,11 @@ public class TileDecoder extends PbfDecoder {
switch (tag) { switch (tag) {
case TAG_WAY_TAGS: case TAG_WAY_TAGS:
tags = decodeWayTags(tagCnt); if (!decodeWayTags(tagCnt))
return false;
break; break;
case TAG_WAY_INDEX: case TAG_WAY_INDEX:
//index =
decodeWayIndices(indexCnt); decodeWayIndices(indexCnt);
break; break;
@ -223,9 +221,9 @@ public class TileDecoder extends PbfDecoder {
} }
} }
if (fail || tags == null || indexCnt == 0 || tagCnt == 0) { if (fail || indexCnt == 0 || tagCnt == 0) {
Log.d(TAG, "failed reading way: bytes:" + bytes + " index:" Log.d(TAG, "failed reading way: bytes:" + bytes + " index:"
+ (tags != null ? tags.toString() : "...") + " " //+ (tags != null ? tags.toString() : "...") + " "
+ indexCnt + " " + coordCnt + " " + tagCnt); + indexCnt + " " + coordCnt + " " + tagCnt);
return false; return false;
} }
@ -234,7 +232,7 @@ public class TileDecoder extends PbfDecoder {
//if (layer == 0) //if (layer == 0)
// layer = 5; // layer = 5;
mElem.type = polygon ? GeometryType.POLY : GeometryType.LINE; mElem.type = polygon ? GeometryType.POLY : GeometryType.LINE;
mElem.set(tags, layer); mElem.setLayer(layer);
mSink.process(mElem); mSink.process(mElem);
return true; return true;
} }
@ -246,7 +244,6 @@ public class TileDecoder extends PbfDecoder {
int tagCnt = 0; int tagCnt = 0;
int coordCnt = 0; int coordCnt = 0;
byte layer = 0; byte layer = 0;
Tag[] tags = null;
while (position() < end) { while (position() < end) {
// read tag and wire type // read tag and wire type
@ -258,11 +255,12 @@ public class TileDecoder extends PbfDecoder {
switch (tag) { switch (tag) {
case TAG_NODE_TAGS: case TAG_NODE_TAGS:
tags = decodeWayTags(tagCnt); if (!decodeWayTags(tagCnt))
return false;
break; break;
case TAG_NODE_COORDS: case TAG_NODE_COORDS:
int cnt = decodeNodeCoordinates(coordCnt, layer, tags); int cnt = decodeNodeCoordinates(coordCnt, layer);
if (cnt != coordCnt) { if (cnt != coordCnt) {
Log.d(TAG, "X wrong number of coordintes"); Log.d(TAG, "X wrong number of coordintes");
return false; return false;
@ -289,7 +287,7 @@ public class TileDecoder extends PbfDecoder {
return true; return true;
} }
private int decodeNodeCoordinates(int numNodes, byte layer, Tag[] tags) private int decodeNodeCoordinates(int numNodes, byte layer)
throws IOException { throws IOException {
int bytes = decodeVarint32(); int bytes = decodeVarint32();
@ -312,48 +310,54 @@ public class TileDecoder extends PbfDecoder {
mElem.index[0] = (short) numNodes; mElem.index[0] = (short) numNodes;
mElem.type = GeometryType.POINT; mElem.type = GeometryType.POINT;
mElem.set(tags, layer); mElem.setLayer(layer);
mSink.process(mElem); mSink.process(mElem);
return cnt; return cnt;
} }
private Tag[] decodeWayTags(int tagCnt) throws IOException { private boolean decodeWayTags(int tagCnt) throws IOException {
int bytes = decodeVarint32(); int bytes = decodeVarint32();
Tag[] tags = new Tag[tagCnt]; mElem.tags.clear();
int cnt = 0; int cnt = 0;
int end = position() + bytes; int end = position() + bytes;
int max = mCurTagCnt; int max = mCurTagCnt;
while (position() < end) { for (; position() < end; cnt++) {
int tagNum = decodeVarint32(); int tagNum = decodeVarint32();
if (tagNum < 0 || cnt == tagCnt) { if (tagNum < 0 || cnt == tagCnt) {
Log.d(TAG, "NULL TAG: " + mTile + " invalid tag:" + tagNum Log.d(TAG, "NULL TAG: " + mTile
+ " invalid tag:" + tagNum
+ " " + tagCnt + "/" + cnt); + " " + tagCnt + "/" + cnt);
} else { continue;
if (tagNum < Tags.MAX) }
tags[cnt++] = Tags.tags[tagNum];
else { if (tagNum < Tags.MAX) {
mElem.tags.add(Tags.tags[tagNum]);
continue;
}
tagNum -= Tags.LIMIT; tagNum -= Tags.LIMIT;
if (tagNum >= 0 && tagNum < max) { if (tagNum >= 0 && tagNum < max) {
// Log.d(TAG, "variable tag: " + curTags[tagNum]); mElem.tags.add(curTags[tagNum]);
tags[cnt++] = curTags[tagNum];
} else { } else {
Log.d(TAG, "NULL TAG: " + mTile + " could find tag:" Log.d(TAG, "NULL TAG: " + mTile
+ tagNum + " " + tagCnt + "/" + cnt); + " could find tag:"
} + tagNum + " " + tagCnt
} + "/" + cnt);
} }
} }
if (tagCnt != cnt) if (tagCnt != cnt) {
Log.d(TAG, "NULL TAG: " + mTile); Log.d(TAG, "NULL TAG: " + mTile);
return false;
}
return tags; return true;
} }
private int decodeWayIndices(int indexCnt) throws IOException { private int decodeWayIndices(int indexCnt) throws IOException {

View File

@ -22,6 +22,7 @@ import java.util.Arrays;
import org.oscim.core.GeometryBuffer.GeometryType; import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.MapElement; import org.oscim.core.MapElement;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.TagSet;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.tilesource.ITileDataSink; import org.oscim.tilesource.ITileDataSink;
import org.oscim.tilesource.ITileDataSource; import org.oscim.tilesource.ITileDataSource;
@ -67,32 +68,24 @@ public class OSciMap2TileSource extends UrlTileSource {
private static final int TAG_ELEM_MIN_HEIGHT = 32; private static final int TAG_ELEM_MIN_HEIGHT = 32;
private static final int TAG_ELEM_PRIORITY = 41; private static final int TAG_ELEM_PRIORITY = 41;
private short[] mSArray = new short[100]; private short[] mSArray;
private final Tag[] mTmpTags = new Tag[20]; private final TagSet mTileTags;
private final Tag[][] mElementTags; private final MapElement mElem;
private final int MAX_TILE_TAGS = 100;
private Tag[] curTags = new Tag[MAX_TILE_TAGS]; private Tile mTile;
private int mCurTagCnt;
private ITileDataSink mMapDataSink;
// scale coordinates to tile size // scale coordinates to tile size
private final static float REF_TILE_SIZE = 4096.0f; private final static float REF_TILE_SIZE = 4096.0f;
private float mScale; private float mScale;
private Tile mTile;
private final MapElement mElem;
private ITileDataSink mMapDataSink;
TileDecoder() { TileDecoder() {
mElem = new MapElement(); mElem = new MapElement();
mTileTags = new TagSet(20);
// reusable tag set // temp array for decoding shorts
Tag[][] tags = new Tag[10][]; mSArray = new short[100];
for (int i = 0; i < 10; i++)
tags[i] = new Tag[i + 1];
mElementTags = tags;
} }
@Override @Override
@ -113,7 +106,7 @@ public class OSciMap2TileSource extends UrlTileSource {
mScale = REF_TILE_SIZE / Tile.SIZE; mScale = REF_TILE_SIZE / Tile.SIZE;
mCurTagCnt = 0; mTileTags.clear();
int val; int val;
int numTags = 0; int numTags = 0;
@ -125,8 +118,6 @@ public class OSciMap2TileSource extends UrlTileSource {
switch (tag) { switch (tag) {
case TAG_TILE_NUM_TAGS: case TAG_TILE_NUM_TAGS:
numTags = decodeVarint32(); numTags = decodeVarint32();
if (numTags > curTags.length)
curTags = new Tag[numTags];
break; break;
case TAG_TILE_TAG_KEYS: case TAG_TILE_TAG_KEYS:
@ -139,7 +130,7 @@ public class OSciMap2TileSource extends UrlTileSource {
case TAG_TILE_TAG_VALUES: case TAG_TILE_TAG_VALUES:
// this wastes one byte, as there is no packed string... // this wastes one byte, as there is no packed string...
decodeTileTags(mCurTagCnt++); decodeTileTags();
break; break;
case TAG_TILE_LINE: case TAG_TILE_LINE:
@ -156,9 +147,11 @@ public class OSciMap2TileSource extends UrlTileSource {
return true; return true;
} }
private boolean decodeTileTags(int curTag) throws IOException { private boolean decodeTileTags() throws IOException {
String tagString = decodeString(); String tagString = decodeString();
int curTag = mTileTags.numTags;
String key = Tags.keys[mSArray[curTag]]; String key = Tags.keys[mSArray[curTag]];
Tag tag; Tag tag;
@ -168,7 +161,8 @@ public class OSciMap2TileSource extends UrlTileSource {
tag = new Tag(key, tagString, true); tag = new Tag(key, tagString, true);
if (debug) if (debug)
Log.d(TAG, mTile + " add tag: " + curTag + " " + tag); Log.d(TAG, mTile + " add tag: " + curTag + " " + tag);
curTags[curTag] = tag;
mTileTags.add(tag);
return true; return true;
} }
@ -194,7 +188,6 @@ public class OSciMap2TileSource extends UrlTileSource {
private boolean decodeTileElement(int type) throws IOException { private boolean decodeTileElement(int type) throws IOException {
int bytes = decodeVarint32(); int bytes = decodeVarint32();
Tag[] tags = null;
short[] index = null; short[] index = null;
int end = position() + bytes; int end = position() + bytes;
@ -223,7 +216,8 @@ public class OSciMap2TileSource extends UrlTileSource {
switch (tag) { switch (tag) {
case TAG_ELEM_TAGS: case TAG_ELEM_TAGS:
tags = decodeElementTags(); if (!decodeElementTags())
return false;
break; break;
case TAG_ELEM_NUM_INDICES: case TAG_ELEM_NUM_INDICES:
@ -269,15 +263,14 @@ public class OSciMap2TileSource extends UrlTileSource {
} }
} }
if (fail || tags == null || indexCnt == 0) { if (fail || indexCnt == 0) {
Log.d(TAG, mTile + " failed reading way: bytes:" + bytes + " index:" Log.d(TAG, mTile + " failed reading way: bytes:" + bytes + " index:"
+ (Arrays.toString(index)) + " tag:" + (Arrays.toString(index)) + " tag:"
+ (tags != null ? Arrays.deepToString(tags) : "null") + " " + (mElem.tags.numTags > 0 ? Arrays.deepToString(mElem.tags.tags) : "null")
+ indexCnt + " " + coordCnt); + " " + indexCnt + " " + coordCnt);
return false; return false;
} }
mElem.tags = tags;
switch (type) { switch (type) {
case TAG_TILE_LINE: case TAG_TILE_LINE:
mElem.type = GeometryType.LINE; mElem.type = GeometryType.LINE;
@ -295,49 +288,46 @@ public class OSciMap2TileSource extends UrlTileSource {
return true; return true;
} }
private Tag[] decodeElementTags() throws IOException { private boolean decodeElementTags() throws IOException {
int bytes = decodeVarint32(); int bytes = decodeVarint32();
Tag[] tmp = mTmpTags; mElem.tags.clear();
int cnt = 0; int cnt = 0;
int end = position() + bytes; int end = position() + bytes;
int max = mCurTagCnt; int max = mTileTags.numTags - 1;
while (position() < end) { for (; position() < end; cnt++) {
int tagNum = decodeVarint32(); int tagNum = decodeVarint32();
if (tagNum < 0) { if (tagNum < 0) {
Log.d(TAG, "NULL TAG: " + mTile + " invalid tag:" + tagNum + " " + cnt); Log.d(TAG, "NULL TAG: " + mTile
} else if (tagNum < Tags.MAX) { + " invalid tag:"
tmp[cnt++] = Tags.tags[tagNum]; + tagNum + " " + cnt);
} else { return false;
}
if (tagNum < Tags.MAX) {
mElem.tags.add(Tags.tags[tagNum]);
continue;
}
tagNum -= Tags.LIMIT; tagNum -= Tags.LIMIT;
if (tagNum >= 0 && tagNum < max) { if (tagNum < 0 || tagNum > max) {
// Log.d(TAG, "variable tag: " + curTags[tagNum]); Log.d(TAG, "NULL TAG: " + mTile
tmp[cnt++] = curTags[tagNum]; + " could not find tag:"
} else {
Log.d(TAG, "NULL TAG: " + mTile + " could not find tag:"
+ tagNum + " " + cnt); + tagNum + " " + cnt);
return false;
} }
}
mElem.tags.add(mTileTags.tags[tagNum]);
} }
if (cnt == 0) { if (cnt == 0) {
Log.d(TAG, "got no TAG!"); Log.d(TAG, "got no TAG!");
return false;
} }
Tag[] tags; return true;
if (cnt < 11)
tags = mElementTags[cnt - 1];
else
tags = new Tag[cnt];
for (int i = 0; i < cnt; i++)
tags[i] = tmp[i];
return tags;
} }
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2013 * Copyright 2013 Hannes Janetzek
* *
* This program is free software: you can redistribute it and/or modify it under the * This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software * terms of the GNU Lesser General Public License as published by the Free Software
@ -54,32 +54,23 @@ public class TileDecoder extends PbfDecoder {
private static final int TAG_ELEM_INDEX = 12; private static final int TAG_ELEM_INDEX = 12;
private static final int TAG_ELEM_COORDS = 13; private static final int TAG_ELEM_COORDS = 13;
private static final int TAG_ELEM_LAYER = 21; private static final int TAG_ELEM_LAYER = 21;
//private static final int TAG_ELEM_HEIGHT = 31;
//private static final int TAG_ELEM_MIN_HEIGHT = 32;
//private static final int TAG_ELEM_PRIORITY = 41;
private short[] mSArray = new short[100]; private short[] mSArray = new short[100];
private Tile mTile; private Tile mTile;
private final MapElement mElem; private final MapElement mElem;
private final Tag[][] mElementTags;
private final TagSet curTags = new TagSet(100); private final TagSet mTileTags;
private ITileDataSink mMapDataSink; private ITileDataSink mMapDataSink;
// scale coordinates to tile size // scale coordinates to tile size
private final static float REF_TILE_SIZE = 4096.0f; private final static float REF_TILE_SIZE = 4096.0f;
private final float mScaleFactor = REF_TILE_SIZE / Tile.SIZE; private final float mScaleFactor = REF_TILE_SIZE / Tile.SIZE;
TileDecoder() { TileDecoder() {
mElem = new MapElement(); mElem = new MapElement();
mTileTags = new TagSet(100);
// reusable tag set
Tag[][] tags = new Tag[10][];
for (int i = 0; i < 10; i++)
tags[i] = new Tag[i + 1];
mElementTags = tags;
} }
@Override @Override
@ -98,7 +89,7 @@ public class TileDecoder extends PbfDecoder {
mTile = tile; mTile = tile;
mMapDataSink = sink; mMapDataSink = sink;
curTags.clear(true); mTileTags.clear(true);
int version = -1; int version = -1;
int val; int val;
@ -218,12 +209,17 @@ public class TileDecoder extends PbfDecoder {
// FIXME filter out all variable tags // FIXME filter out all variable tags
// might depend on theme though // might depend on theme though
if (key == Tag.TAG_KEY_NAME || key == Tag.KEY_HEIGHT || key == Tag.KEY_MIN_HEIGHT) if (key == Tag.TAG_KEY_NAME
|| key == Tag.KEY_HEIGHT
|| key == Tag.KEY_MIN_HEIGHT
|| key == Tag.TAG_KEY_HOUSE_NUMBER
|| key == Tag.TAG_KEY_REF
|| key == Tag.TAG_KEY_ELE)
tag = new Tag(key, val, false); tag = new Tag(key, val, false);
else else
tag = new Tag(key, val, true); tag = new Tag(key, val, true);
curTags.add(tag); mTileTags.add(tag);
} }
return true; return true;
@ -251,7 +247,6 @@ public class TileDecoder extends PbfDecoder {
private boolean decodeTileElement(int type) throws IOException { private boolean decodeTileElement(int type) throws IOException {
int bytes = decodeVarint32(); int bytes = decodeVarint32();
Tag[] tags = null;
short[] index = null; short[] index = null;
int end = position() + bytes; int end = position() + bytes;
@ -282,7 +277,8 @@ public class TileDecoder extends PbfDecoder {
switch (tag) { switch (tag) {
case TAG_ELEM_TAGS: case TAG_ELEM_TAGS:
tags = decodeElementTags(numTags); if (!decodeElementTags(numTags))
return false;
break; break;
case TAG_ELEM_NUM_INDICES: case TAG_ELEM_NUM_INDICES:
@ -322,15 +318,14 @@ public class TileDecoder extends PbfDecoder {
} }
} }
if (fail || tags == null || numIndices == 0) { if (fail || numTags == 0 || numIndices == 0) {
Log.d(TAG, mTile + " failed reading way: bytes:" + bytes + " index:" Log.d(TAG, mTile + " failed reading way: bytes:" + bytes + " index:"
+ (Arrays.toString(index)) + " tag:" + (Arrays.toString(index)) + " tag:"
+ (tags != null ? Arrays.deepToString(tags) : "null") + " " + (mElem.tags.numTags > 0 ? Arrays.deepToString(mElem.tags.tags) : "null")
+ numIndices + " " + coordCnt); + " " + numIndices + " " + coordCnt);
return false; return false;
} }
mElem.tags = tags;
switch (type) { switch (type) {
case TAG_TILE_LINE: case TAG_TILE_LINE:
mElem.type = GeometryType.LINE; mElem.type = GeometryType.LINE;
@ -348,33 +343,27 @@ public class TileDecoder extends PbfDecoder {
return true; return true;
} }
private Tag[] decodeElementTags(int numTags) throws IOException { private boolean decodeElementTags(int numTags) throws IOException {
if (mSArray.length < numTags) if (mSArray.length < numTags)
mSArray = new short[numTags]; mSArray = new short[numTags];
short[] tagIds = mSArray; short[] tagIds = mSArray;
decodeVarintArray(numTags, tagIds); decodeVarintArray(numTags, tagIds);
Tag[] tags; mElem.tags.clear();
if (numTags < 11) int max = mTileTags.numTags - 1;
tags = mElementTags[numTags - 1];
else
tags = new Tag[numTags];
int max = curTags.numTags;
for (int i = 0; i < numTags; i++) { for (int i = 0; i < numTags; i++) {
int idx = tagIds[i]; int idx = tagIds[i];
if (idx < 0 || idx > max) { if (idx < 0 || idx > max) {
Log.d(TAG, mTile + " invalid tag:" + idx + " " + i); Log.d(TAG, mTile + " invalid tag:" + idx + " " + i);
return null; return false;
}
mElem.tags.add(mTileTags.tags[idx]);
} }
tags[i] = curTags.tags[idx]; return true;
}
return tags;
} }
} }

View File

@ -94,7 +94,7 @@ public class TestTileSource implements ITileDataSource {
e.addPoint(x2, y2); e.addPoint(x2, y2);
e.addPoint(x1, y2); e.addPoint(x1, y2);
e.set(mTags, 0); //// FIXME e.setLayer(mTags, 0);
mapDataSink.process(e); mapDataSink.process(e);
if (renderWays) { if (renderWays) {
@ -115,7 +115,7 @@ public class TestTileSource implements ITileDataSource {
e.addPoint(size / 2, size / 2); e.addPoint(size / 2, size / 2);
e.addPoint(size / 2, size / 2 + size); e.addPoint(size / 2, size / 2 + size);
e.set(mTagsWay, 0); ////e.setLayer(mTagsWay, 0);
mapDataSink.process(e); mapDataSink.process(e);
e.clear(); e.clear();
@ -132,7 +132,7 @@ public class TestTileSource implements ITileDataSource {
e.addPoint(10, 0); e.addPoint(10, 0);
e.addPoint(10, size); e.addPoint(10, size);
e.set(mTagsWay, 1); //// --e.setLayer(mTagsWay, 1);
mapDataSink.process(e); mapDataSink.process(e);
} }
@ -147,7 +147,7 @@ public class TestTileSource implements ITileDataSource {
r + (float) Math.sin(d) * (r - 40)); r + (float) Math.sin(d) * (r - 40));
} }
e.set(mTagsBoundary, 1); //// e.setLayer(mTagsBoundary, 1);
mapDataSink.process(e); mapDataSink.process(e);
} }
@ -157,7 +157,7 @@ public class TestTileSource implements ITileDataSource {
e.addPoint(size / 2, size / 2); e.addPoint(size / 2, size / 2);
mTagsPlace[1] = new Tag("name", tile.toString()); mTagsPlace[1] = new Tag("name", tile.toString());
e.set(mTagsPlace, 0); //// e.setLayer(mTagsPlace, 0);
mapDataSink.process(e); mapDataSink.process(e);
} }
return QueryResult.SUCCESS; return QueryResult.SUCCESS;