Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2013 Hannes Janetzek
* Copyright 2016-2017 devemux86
* Copyright 2017 Gustl22
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* 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
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see .
*/
package org.oscim.tiling.source.oscimap4;
import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.MapElement;
import org.oscim.core.Tag;
import org.oscim.core.TagSet;
import org.oscim.core.Tile;
import org.oscim.tiling.ITileDataSink;
import org.oscim.tiling.source.PbfDecoder;
import org.oscim.utils.FastMath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
public class TileDecoder extends PbfDecoder {
static final Logger log = LoggerFactory.getLogger(TileDecoder.class);
private static final int TAG_TILE_VERSION = 1;
//private static final int TAG_TILE_TIMESTAMP = 2;
//private static final int TAG_TILE_ISWATER = 3;
private static final int TAG_TILE_NUM_TAGS = 11;
private static final int TAG_TILE_NUM_KEYS = 12;
private static final int TAG_TILE_NUM_VALUES = 13;
private static final int TAG_TILE_TAG_KEYS = 14;
private static final int TAG_TILE_TAG_VALUES = 15;
private static final int TAG_TILE_TAGS = 16;
private static final int TAG_TILE_LINE = 21;
private static final int TAG_TILE_POLY = 22;
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_TAGS = 2;
/**
* 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_INDEX = 12;
private static final int TAG_ELEM_COORDS = 13;
private static final int TAG_ELEM_LAYER = 21;
private int[] mSArray = new int[100];
private Tile mTile;
private final MapElement mElem;
private final TagSet mTileTags;
private ITileDataSink mMapDataSink;
private int mVersion;
// scale coordinates to tile size
private static final float REF_TILE_SIZE = 4096.0f;
private final float mScaleFactor = REF_TILE_SIZE / Tile.SIZE;
public TileDecoder() {
mElem = new MapElement();
mTileTags = new TagSet(100);
}
@Override
public boolean decode(Tile tile, ITileDataSink sink, InputStream is)
throws IOException {
readUnsignedInt(is, buffer);
setInputStream(is);
mTile = tile;
mMapDataSink = sink;
mTileTags.clearAndNullTags();
int val;
int numTags = 0;
int numKeys = -1;
int numValues = -1;
int curKey = 0;
int curValue = 0;
String[] keys = null;
String[] values = null;
while (hasData() && (val = decodeVarint32()) > 0) {
// read tag and wire type
int tag = (val >> 3);
//log.debug("tag: " + tag);
switch (tag) {
case TAG_TILE_LINE:
case TAG_TILE_POLY:
case TAG_TILE_POINT:
case TAG_TILE_MESH:
decodeTileElement(tag);
break;
case TAG_TILE_TAG_KEYS:
if (keys == null || curKey >= numKeys) {
log.debug("{} wrong number of keys {}",
mTile, numKeys);
return false;
}
keys[curKey++] = decodeString().intern();
break;
case TAG_TILE_TAG_VALUES:
if (values == null || curValue >= numValues) {
log.debug("{} wrong number of values {}",
mTile, numValues);
return false;
}
values[curValue++] = decodeString();
break;
case TAG_TILE_NUM_TAGS:
numTags = decodeVarint32();
//log.debug("num tags " + numTags);
break;
case TAG_TILE_NUM_KEYS:
numKeys = decodeVarint32();
//log.debug("num keys " + numKeys);
keys = new String[numKeys];
break;
case TAG_TILE_NUM_VALUES:
numValues = decodeVarint32();
//log.debug("num values " + numValues);
values = new String[numValues];
break;
case TAG_TILE_TAGS:
int len = numTags * 2;
if (mSArray.length < len)
mSArray = new int[len];
decodeVarintArray(len, mSArray);
if (!decodeTileTags(numTags, mSArray, keys, values)) {
log.debug("{} invalid tags", mTile);
return false;
}
break;
case TAG_TILE_VERSION:
int version = decodeVarint32();
if (version < 4 || mVersion > 5) {
log.debug("{} invalid version:{}",
mTile, version);
return false;
}
break;
default:
log.debug("{} invalid type for tile:{}",
mTile, tag);
return false;
}
}
return true;
}
private boolean decodeTileTags(int numTags, int[] tagIdx,
String[] keys, String[] vals) {
Tag tag;
for (int i = 0, n = (numTags << 1); i < n; i += 2) {
int k = tagIdx[i];
int v = tagIdx[i + 1];
String key, val;
if (k < Tags.ATTRIB_OFFSET) {
if (k > Tags.MAX_KEY)
return false;
key = Tags.keys[k];
} else {
k -= Tags.ATTRIB_OFFSET;
if (k >= keys.length)
return false;
key = keys[k];
}
if (v < Tags.ATTRIB_OFFSET) {
if (v > Tags.MAX_VALUE)
return false;
val = Tags.values[v];
} else {
v -= Tags.ATTRIB_OFFSET;
if (v >= vals.length)
return false;
val = vals[v];
}
// FIXME filter out all variable tags
// might depend on theme though
if (Tag.KEY_NAME.equals(key)
|| Tag.KEY_HOUSE_NUMBER.equals(key)
|| Tag.KEY_REF.equals(key)
|| Tag.KEY_ELE.equals(key))
tag = new Tag(key, val, false);
else if (Tag.KEY_HEIGHT.equals(key)
|| Tag.KEY_MIN_HEIGHT.equals(key)) {
// Reformat values to established meters in OSM
tag = new Tag(key, String.valueOf(FastMath.round2(Float.valueOf(val) / 100)), false);
} else
tag = new Tag(key, val, false, true);
mTileTags.add(tag);
}
return true;
}
private int decodeWayIndices(int indexCnt, boolean shift) throws IOException {
mElem.ensureIndexSize(indexCnt, false);
decodeVarintArray(indexCnt, mElem.index);
int[] index = mElem.index;
int coordCnt = 0;
if (shift) {
for (int i = 0; i < indexCnt; i++) {
coordCnt += index[i];
index[i] *= 2;
}
}
// set end marker
if (indexCnt < index.length)
index[indexCnt] = -1;
return coordCnt;
}
private boolean decodeTileElement(int type) throws IOException {
int bytes = decodeVarint32();
int end = position() + bytes;
int numIndices = 1;
int numTags = 1;
//boolean skip = false;
boolean fail = false;
int coordCnt = 0;
if (type == TAG_TILE_POINT) {
coordCnt = 1;
mElem.index[0] = 2;
}
mElem.layer = 5;
while (position() < end) {
// read tag and wire type
int val = decodeVarint32();
if (val == 0)
break;
int tag = (val >> 3);
switch (tag) {
case TAG_ELEM_TAGS:
if (!decodeElementTags(numTags))
return false;
break;
case TAG_ELEM_NUM_INDICES:
numIndices = decodeVarint32();
break;
case TAG_ELEM_NUM_TAGS:
numTags = decodeVarint32();
break;
case TAG_ELEM_NUM_COORDINATES:
coordCnt = decodeVarint32();
break;
case TAG_ELEM_INDEX:
if (type == TAG_TILE_MESH) {
decodeWayIndices(numIndices, false);
} else {
coordCnt = decodeWayIndices(numIndices, true);
// otherwise using TAG_ELEM_NUM_COORDINATES
}
break;
case TAG_ELEM_COORDS:
if (coordCnt == 0) {
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.pointNextPos = cnt;
} else {
mElem.ensurePointSize(coordCnt, false);
int cnt = decodeInterleavedPoints(mElem, mScaleFactor);
if (cnt != coordCnt) {
log.debug("{} wrong number of coordintes {}/{}", mTile,
Integer.valueOf(coordCnt),
Integer.valueOf(cnt));
fail = true;
}
}
break;
case TAG_ELEM_LAYER:
mElem.layer = decodeVarint32();
break;
default:
log.debug("{} invalid type for way: {}", mTile, tag);
}
}
if (fail || numTags == 0 || numIndices == 0) {
log.debug("{} failed: bytes:{} tags:{} ({},{})",
mTile, Integer.valueOf(bytes),
mElem.tags,
Integer.valueOf(numIndices),
Integer.valueOf(coordCnt));
return false;
}
switch (type) {
case TAG_TILE_LINE:
mElem.type = GeometryType.LINE;
break;
case TAG_TILE_POLY:
mElem.type = GeometryType.POLY;
break;
case TAG_TILE_POINT:
mElem.type = GeometryType.POINT;
break;
case TAG_TILE_MESH:
mElem.type = GeometryType.TRIS;
break;
}
mMapDataSink.process(mElem);
return true;
}
private boolean decodeElementTags(int numTags) throws IOException {
if (mSArray.length < numTags)
mSArray = new int[numTags];
int[] tagIds = mSArray;
decodeVarintArray(numTags, tagIds);
mElem.tags.clear();
int max = mTileTags.size() - 1;
for (int i = 0; i < numTags; i++) {
int idx = tagIds[i];
if (idx < 0 || idx > max) {
log.debug("{} invalid tag:{}", mTile,
Integer.valueOf(idx),
Integer.valueOf(i));
return false;
}
mElem.tags.add(mTileTags.get(idx));
}
return true;
}
}