improve tag-replacement(for theme cache) in VectorTileLoader

This commit is contained in:
Hannes Janetzek 2013-09-29 14:41:11 +02:00
parent 7c090e921a
commit 206003e1ec
3 changed files with 58 additions and 104 deletions

View File

@ -56,41 +56,31 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
public static final byte STROKE_MIN_ZOOM = 12; public static final byte STROKE_MIN_ZOOM = 12;
public static final byte STROKE_MAX_ZOOM = 17; public static final byte STROKE_MAX_ZOOM = 17;
//private static final Tag[] debugTagWay = { new Tag("debug", "way") };
//private static final Tag[] debugTagArea = { new Tag("debug", "area") };
// replacement for variable value tags that should not be matched by RenderTheme
// FIXME make this general, maybe subclass tags
private static final Tag mTagEmptyName = new Tag(Tag.KEY_NAME, null, false);
private static final Tag mTagEmptyHouseNr = new Tag(Tag.KEY_HOUSE_NUMBER, null, false);
// private final MapElement mDebugWay, mDebugPoint;
private IRenderTheme renderTheme; private IRenderTheme renderTheme;
private int renderLevels; private int renderLevels;
// current TileDataSource used by this MapTileLoader /** current TileDataSource used by this MapTileLoader */
private ITileDataSource mTileDataSource; private ITileDataSource mTileDataSource;
// currently processed tile /** currently processed tile */
private MapTile mTile; private MapTile mTile;
// currently processed MapElement /** currently processed MapElement */
private MapElement mElement; private MapElement mElement;
// current line layer (will be used for following outline layers) /** current line layer (will be used for outline layers) */
private LineLayer mCurLineLayer; private LineLayer mCurLineLayer;
private int mDrawingLayer; /** Current layer for adding elements */
private int mCurLayer;
/** Line-scale-factor depending on zoom and latitude */
private float mLineScale = 1.0f; private float mLineScale = 1.0f;
private float mGroundScale;
private Tag mTagName;
private Tag mTagHouseNr;
private final LineClipper mClipper; private final LineClipper mClipper;
private final TagSet mFilteredTags;
public void setRenderTheme(IRenderTheme theme) { public void setRenderTheme(IRenderTheme theme) {
renderTheme = theme; renderTheme = theme;
renderLevels = theme.getLevels(); renderLevels = theme.getLevels();
@ -100,6 +90,7 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
super(tileManager); super(tileManager);
mClipper = new LineClipper(0, 0, Tile.SIZE, Tile.SIZE, true); mClipper = new LineClipper(0, 0, Tile.SIZE, Tile.SIZE, true);
mFilteredTags = new TagSet();
} }
@Override @Override
@ -123,10 +114,6 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
// scale line width relative to latitude + PI * thumb // scale line width relative to latitude + PI * thumb
mLineScale *= 0.4f + 0.6f * ((float) Math.sin(Math.abs(lat) * (Math.PI / 180))); mLineScale *= 0.4f + 0.6f * ((float) Math.sin(Math.abs(lat) * (Math.PI / 180)));
mGroundScale = (float) (Math.cos(lat * (Math.PI / 180))
* MercatorProjection.EARTH_CIRCUMFERENCE
/ ((long) Tile.SIZE << tile.zoomLevel));
mTile = tile; mTile = tile;
mTile.layers = new ElementLayers(); mTile.layers = new ElementLayers();
@ -137,26 +124,9 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
clearState(); clearState();
// if (debug.drawTileFrames) {
// // draw tile coordinate
// mTagName = new Tag("name", mTile.toString(), false);
// mElement = mDebugPoint;
// RenderInstruction[] ri;
// ri = renderTheme.matchNode(debugTagWay, (byte) 0);
// renderNode(ri);
//
// // draw tile box
// mElement = mDebugWay;
// mDrawingLayer = 100 * renderLevels;
// ri = renderTheme.matchWay(mDebugWay.tags, (byte) 0, false);
// renderWay(ri);
// }
return (result == QueryResult.SUCCESS); return (result == QueryResult.SUCCESS);
} }
Tag[] mFilterTags = new Tag[1];
private static int getValidLayer(int layer) { private static int getValidLayer(int layer) {
if (layer < 0) { if (layer < 0) {
return 0; return 0;
@ -174,49 +144,47 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
mTileDataSource = mapDatabase; mTileDataSource = mapDatabase;
} }
private boolean mRenderBuildingModel; static class TagReplacement {
public TagReplacement(String key) {
this.key = key;
this.tag = new Tag(key, null);
}
String key;
Tag tag;
}
// Replace tags that should only be matched by key in RenderTheme // Replace tags that should only be matched by key in RenderTheme
// to avoid caching RenderInstructions for each way of the same type // to avoid caching RenderInstructions for each way of the same type
// 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(TagSet in) { private static final TagReplacement[] mTagReplacement = {
mRenderBuildingModel = false; new TagReplacement(Tag.KEY_NAME),
Tag[] tags = in.tags; new TagReplacement(Tag.KEY_HOUSE_NUMBER),
new TagReplacement(Tag.KEY_REF),
new TagReplacement(Tag.KEY_HEIGHT),
new TagReplacement(Tag.KEY_MIN_HEIGHT)
};
for (int i = 0; i < in.numTags; i++) { private boolean filterTags(TagSet tagSet) {
String key = tags[i].key; Tag[] tags = tagSet.tags;
if (tags[i].key == Tag.KEY_NAME) {
if (tags[i].value != null) {
mTagName = tags[i];
tags[i] = mTagEmptyName;
}
} else if (tags[i].key == Tag.KEY_HOUSE_NUMBER) {
if (tags[i].value != null) {
mTagHouseNr = tags[i];
tags[i] = mTagEmptyHouseNr;
}
} else if (mTile.zoomLevel > 16) {
// FIXME, allow overlays to intercept
// this, or use a theme option for this
if (key == Tag.KEY_BUILDING)
mRenderBuildingModel = true;
else if (key == Tag.KEY_HEIGHT) { mFilteredTags.clear();
try {
mElement.height = Integer.parseInt(tags[i].value); O: for (int i = 0, n = tagSet.numTags; i < n; i++) {
} catch (Exception e) { Tag t = tags[i];
}
} for (TagReplacement replacement : mTagReplacement) {
else if (key == Tag.KEY_MIN_HEIGHT) { if (t.key == replacement.key) {
try { mFilteredTags.add(replacement.tag);
mElement.minHeight = Integer.parseInt(tags[i].value); continue O;
} catch (Exception e) {
}
} }
} }
mFilteredTags.add(t);
} }
return true; return true;
} }
@ -231,17 +199,17 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
filterTags(element.tags); filterTags(element.tags);
// get and apply render instructions // get and apply render instructions
renderNode(renderTheme.matchElement(element, mTile.zoomLevel)); renderNode(renderTheme.matchElement(element.type, mFilteredTags, mTile.zoomLevel));
} else { } else {
// replace tags that should not be cached in Rendertheme (e.g. name) // replace tags that should not be cached in Rendertheme (e.g. name)
if (!filterTags(element.tags)) if (!filterTags(element.tags))
return; return;
mDrawingLayer = getValidLayer(element.layer) * renderLevels; mCurLayer = getValidLayer(element.layer) * renderLevels;
// get and apply render instructions // get and apply render instructions
renderWay(renderTheme.matchElement(element, mTile.zoomLevel)); renderWay(renderTheme.matchElement(element.type, mFilteredTags, mTile.zoomLevel));
//boolean closed = element.type == GeometryType.POLY; //boolean closed = element.type == GeometryType.POLY;
//if (debug.debugTheme && ri == null) //if (debug.debugTheme && ri == null)
@ -282,15 +250,13 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
} }
private void clearState() { private void clearState() {
mTagName = null;
mTagHouseNr = null;
mCurLineLayer = null; mCurLineLayer = null;
} }
/*** RenderThemeCallback ***/ /*** RenderThemeCallback ***/
@Override @Override
public void renderWay(Line line, int level) { public void renderWay(Line line, int level) {
int numLayer = mDrawingLayer + level; int numLayer = mCurLayer + level;
if (line.stipple == 0) { if (line.stipple == 0) {
if (line.outline && mCurLineLayer == null) { if (line.outline && mCurLineLayer == null) {
@ -345,7 +311,7 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
@Override @Override
public void renderArea(Area area, int level) { public void renderArea(Area area, int level) {
int numLayer = mDrawingLayer + level; int numLayer = mCurLayer + level;
PolygonLayer layer = mTile.layers.getPolygonLayer(numLayer); PolygonLayer layer = mTile.layers.getPolygonLayer(numLayer);
@ -356,24 +322,10 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
layer.addPolygon(mElement.points, mElement.index); layer.addPolygon(mElement.points, mElement.index);
} }
private String textValueForKey(Text text) {
String value = null;
if (text.textKey == Tag.KEY_NAME) {
if (mTagName != null)
value = mTagName.value;
} else if (text.textKey == Tag.KEY_HOUSE_NUMBER) {
if (mTagHouseNr != null)
value = mTagHouseNr.value;
}
return value;
}
@Override @Override
public void renderAreaText(Text text) { public void renderAreaText(Text text) {
// TODO place somewhere on polygon // TODO place somewhere on polygon
String value = mElement.tags.getValue(text.textKey);
String value = textValueForKey(text);
if (value == null) if (value == null)
return; return;
@ -383,7 +335,7 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
@Override @Override
public void renderPointText(Text text) { public void renderPointText(Text text) {
String value = textValueForKey(text); String value = mElement.tags.getValue(text.textKey);
if (value == null) if (value == null)
return; return;
@ -395,7 +347,7 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
@Override @Override
public void renderWayText(Text text) { public void renderWayText(Text text) {
String value = textValueForKey(text); String value = mElement.tags.getValue(text.textKey);
if (value == null) if (value == null)
return; return;

View File

@ -15,7 +15,8 @@
*/ */
package org.oscim.theme; package org.oscim.theme;
import org.oscim.core.MapElement; import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.TagSet;
import org.oscim.theme.renderinstruction.Area; import org.oscim.theme.renderinstruction.Area;
import org.oscim.theme.renderinstruction.Circle; import org.oscim.theme.renderinstruction.Circle;
import org.oscim.theme.renderinstruction.Line; import org.oscim.theme.renderinstruction.Line;
@ -33,7 +34,7 @@ public interface IRenderTheme {
* the zoom level at which the way should be matched. * the zoom level at which the way should be matched.
* @return matching render instructions * @return matching render instructions
*/ */
public abstract RenderInstruction[] matchElement(MapElement element, int zoomLevel); public abstract RenderInstruction[] matchElement(GeometryType type, TagSet tags, int zoomLevel);
/** /**
* Must be called when this RenderTheme gets destroyed to clean up and free * Must be called when this RenderTheme gets destroyed to clean up and free

View File

@ -20,7 +20,8 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import org.oscim.backend.Log; import org.oscim.backend.Log;
import org.oscim.core.MapElement; import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.TagSet;
import org.oscim.theme.renderinstruction.RenderInstruction; import org.oscim.theme.renderinstruction.RenderInstruction;
import org.oscim.theme.rule.Element; import org.oscim.theme.rule.Element;
import org.oscim.theme.rule.Rule; import org.oscim.theme.rule.Rule;
@ -106,7 +107,7 @@ public class RenderTheme implements IRenderTheme {
} }
@Override @Override
public RenderInstruction[] matchElement(MapElement element, int zoomLevel) { public RenderInstruction[] matchElement(GeometryType geometryType, TagSet tags, int zoomLevel) {
// list of renderinsctruction items in cache // list of renderinsctruction items in cache
RenderInstructionItem ris = null; RenderInstructionItem ris = null;
@ -114,9 +115,9 @@ public class RenderTheme implements IRenderTheme {
// the item matching tags and zoomlevel // the item matching tags and zoomlevel
RenderInstructionItem ri = null; RenderInstructionItem ri = null;
int type = element.type.nativeInt; int type = geometryType.nativeInt;
if (type < 1 || type > 3) { if (type < 1 || type > 3) {
Log.d(TAG, "invalid geometry type for RenderTheme " + element.type.name()); Log.d(TAG, "invalid geometry type for RenderTheme " + geometryType.name());
return null; return null;
} }
@ -129,10 +130,10 @@ public class RenderTheme implements IRenderTheme {
if ((cache.prevItem == null) || (cache.prevItem.zoom & zoomMask) == 0) { if ((cache.prevItem == null) || (cache.prevItem.zoom & zoomMask) == 0) {
// previous instructions zoom does not match // previous instructions zoom does not match
cache.cacheKey.set(element.tags, null); cache.cacheKey.set(tags, null);
} else { } else {
// compare if tags match previous instructions // compare if tags match previous instructions
if (cache.cacheKey.set(element.tags, cache.prevItem.key)) { if (cache.cacheKey.set(tags, cache.prevItem.key)) {
//Log.d(TAG, "same as previous " + Arrays.deepToString(tags)); //Log.d(TAG, "same as previous " + Arrays.deepToString(tags));
ri = cache.prevItem; ri = cache.prevItem;
} }