s3db: add triangle geometry decoder

This commit is contained in:
Hannes Janetzek 2014-03-21 01:46:07 +01:00
parent 27750ac11e
commit fb3e50cc88
2 changed files with 114 additions and 21 deletions

View File

@ -250,6 +250,71 @@ public abstract class PbfDecoder implements ITileDecoder {
return (cnt >> 1); return (cnt >> 1);
} }
protected int decodeInterleavedPoints3D(float[] coords, float scale)
throws IOException {
int bytes = decodeVarint32();
fillBuffer(bytes);
int cnt = 0;
int lastX = 0;
int lastY = 0;
int lastZ = 0;
int cur = 0;
byte[] buf = buffer;
int pos = bufferPos;
int end = pos + bytes;
while (pos < end) {
byte b = buf[pos++];
int val = b;
if (b < 0) {
b = buf[pos++];
val = (val & M1) | (b << S1);
if (b < 0) {
b = buf[pos++];
val = (val & M2) | (b << S2);
if (b < 0) {
b = buf[pos++];
val = (val & M3) | (b << S3);
if (b < 0) {
b = buf[pos++];
val = (val & M4) | (b << S4);
if (b < 0)
throw INVALID_VARINT;
}
}
}
}
// zigzag decoding
int s = ((val >>> 1) ^ -(val & 1));
if (cur == 0) {
lastX = lastX + s;
coords[cnt++] = lastX / scale;
} else if (cur == 1) {
lastY = lastY + s;
coords[cnt++] = lastY / scale;
} else {
lastZ = lastZ + s;
coords[cnt++] = lastZ / scale;
}
cur = (cur + 1) % 3;
}
if (pos != bufferPos + bytes)
throw INVALID_PACKED_SIZE;
bufferPos = pos;
// return number of points read
//FIXME inconsitent with 3d version!
return cnt;
}
protected static int deZigZag(int val) { protected static int deZigZag(int val) {
return ((val >>> 1) ^ -(val & 1)); return ((val >>> 1) ^ -(val & 1));
} }

View File

@ -18,7 +18,6 @@ package org.oscim.tiling.source.oscimap4;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
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;
@ -48,10 +47,13 @@ public class TileDecoder extends PbfDecoder {
private static final int TAG_TILE_LINE = 21; private static final int TAG_TILE_LINE = 21;
private static final int TAG_TILE_POLY = 22; private static final int TAG_TILE_POLY = 22;
private static final int TAG_TILE_POINT = 23; private static final int TAG_TILE_POINT = 23;
/** since version 5 */
private static final int TAG_TILE_MESH = 24;
private static final int TAG_ELEM_NUM_INDICES = 1; private static final int TAG_ELEM_NUM_INDICES = 1;
private static final int TAG_ELEM_NUM_TAGS = 2; private static final int TAG_ELEM_NUM_TAGS = 2;
//private static final int TAG_ELEM_HAS_ELEVATION = 3; /** since version 5 */
private static final int TAG_ELEM_NUM_COORDINATES = 3;
private static final int TAG_ELEM_TAGS = 11; private static final int TAG_ELEM_TAGS = 11;
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;
@ -66,6 +68,8 @@ public class TileDecoder extends PbfDecoder {
private final TagSet mTileTags; private final TagSet mTileTags;
private ITileDataSink mMapDataSink; private ITileDataSink mMapDataSink;
private int mVersion;
// 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;
@ -86,7 +90,6 @@ public class TileDecoder extends PbfDecoder {
mMapDataSink = sink; mMapDataSink = sink;
mTileTags.clearAndNullTags(); mTileTags.clearAndNullTags();
int version = -1;
int val; int val;
int numTags = 0; int numTags = 0;
@ -108,6 +111,7 @@ public class TileDecoder extends PbfDecoder {
case TAG_TILE_LINE: case TAG_TILE_LINE:
case TAG_TILE_POLY: case TAG_TILE_POLY:
case TAG_TILE_POINT: case TAG_TILE_POINT:
case TAG_TILE_MESH:
decodeTileElement(tag); decodeTileElement(tag);
break; break;
@ -159,8 +163,8 @@ public class TileDecoder extends PbfDecoder {
break; break;
case TAG_TILE_VERSION: case TAG_TILE_VERSION:
version = decodeVarint32(); int version = decodeVarint32();
if (version != 4) { if (version < 4 || mVersion > 5) {
log.debug("{} invalid version:{}", log.debug("{} invalid version:{}",
mTile, version); mTile, version);
return false; return false;
@ -226,18 +230,19 @@ public class TileDecoder extends PbfDecoder {
return true; return true;
} }
private int decodeWayIndices(int indexCnt) throws IOException { private int decodeWayIndices(int indexCnt, boolean shift) throws IOException {
mElem.ensureIndexSize(indexCnt, false); mElem.ensureIndexSize(indexCnt, false);
decodeVarintArray(indexCnt, mElem.index); decodeVarintArray(indexCnt, mElem.index);
short[] index = mElem.index; short[] index = mElem.index;
int coordCnt = 0; int coordCnt = 0;
if (shift) {
for (int i = 0; i < indexCnt; i++) { for (int i = 0; i < indexCnt; i++) {
coordCnt += index[i]; coordCnt += index[i];
index[i] *= 2; index[i] *= 2;
} }
}
// set end marker // set end marker
if (indexCnt < index.length) if (indexCnt < index.length)
index[indexCnt] = -1; index[indexCnt] = -1;
@ -248,7 +253,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();
short[] index = null;
int end = position() + bytes; int end = position() + bytes;
int numIndices = 1; int numIndices = 1;
@ -287,8 +291,17 @@ public class TileDecoder extends PbfDecoder {
numTags = decodeVarint32(); numTags = decodeVarint32();
break; break;
case TAG_ELEM_NUM_COORDINATES:
coordCnt = decodeVarint32();
break;
case TAG_ELEM_INDEX: case TAG_ELEM_INDEX:
coordCnt = decodeWayIndices(numIndices); if (type == TAG_TILE_MESH) {
decodeWayIndices(numIndices, false);
} else {
coordCnt = decodeWayIndices(numIndices, true);
// otherwise using TAG_ELEM_NUM_COORDINATES
}
break; break;
case TAG_ELEM_COORDS: case TAG_ELEM_COORDS:
@ -296,6 +309,18 @@ public class TileDecoder extends PbfDecoder {
log.debug("{} no coordinates", mTile); log.debug("{} no coordinates", mTile);
} }
if (type == TAG_TILE_MESH) {
mElem.ensurePointSize((coordCnt * 3 / 2), false);
int cnt = decodeInterleavedPoints3D(mElem.points, 1);
if (cnt != (3 * coordCnt)) {
log.debug("{} wrong number of coordintes {}/{}", mTile,
Integer.valueOf(coordCnt),
Integer.valueOf(cnt));
fail = true;
}
mElem.pointPos = cnt;
} else {
mElem.ensurePointSize(coordCnt, false); mElem.ensurePointSize(coordCnt, false);
int cnt = decodeInterleavedPoints(mElem, mScaleFactor); int cnt = decodeInterleavedPoints(mElem, mScaleFactor);
@ -305,6 +330,7 @@ public class TileDecoder extends PbfDecoder {
Integer.valueOf(cnt)); Integer.valueOf(cnt));
fail = true; fail = true;
} }
}
break; break;
case TAG_ELEM_LAYER: case TAG_ELEM_LAYER:
@ -317,9 +343,8 @@ public class TileDecoder extends PbfDecoder {
} }
if (fail || numTags == 0 || numIndices == 0) { if (fail || numTags == 0 || numIndices == 0) {
log.debug("{} failed: bytes:{} index:{} tags:{} ({},{})", log.debug("{} failed: bytes:{} tags:{} ({},{})",
mTile, Integer.valueOf(bytes), mTile, Integer.valueOf(bytes),
Arrays.toString(index),
mElem.tags, mElem.tags,
Integer.valueOf(numIndices), Integer.valueOf(numIndices),
Integer.valueOf(coordCnt)); Integer.valueOf(coordCnt));
@ -336,6 +361,9 @@ public class TileDecoder extends PbfDecoder {
case TAG_TILE_POINT: case TAG_TILE_POINT:
mElem.type = GeometryType.POINT; mElem.type = GeometryType.POINT;
break; break;
case TAG_TILE_MESH:
mElem.type = GeometryType.TRIS;
break;
} }
mMapDataSink.process(mElem); mMapDataSink.process(mElem);