update GWT emulation
This commit is contained in:
parent
53572671de
commit
d1fa4d426f
@ -18,6 +18,7 @@ import org.oscim.backend.Log;
|
||||
import org.oscim.core.GeometryBuffer.GeometryType;
|
||||
import org.oscim.core.MapElement;
|
||||
import org.oscim.core.MercatorProjection;
|
||||
import org.oscim.core.PointF;
|
||||
import org.oscim.core.Tag;
|
||||
import org.oscim.core.TagSet;
|
||||
import org.oscim.core.Tile;
|
||||
@ -32,6 +33,7 @@ import org.oscim.renderer.elements.TextItem;
|
||||
import org.oscim.theme.IRenderTheme;
|
||||
import org.oscim.theme.renderinstruction.Area;
|
||||
import org.oscim.theme.renderinstruction.Circle;
|
||||
import org.oscim.theme.renderinstruction.Extrusion;
|
||||
import org.oscim.theme.renderinstruction.Line;
|
||||
import org.oscim.theme.renderinstruction.LineSymbol;
|
||||
import org.oscim.theme.renderinstruction.RenderInstruction;
|
||||
@ -44,18 +46,7 @@ import org.oscim.tiling.source.ITileDataSink;
|
||||
import org.oscim.tiling.source.ITileDataSource;
|
||||
import org.oscim.tiling.source.ITileDataSource.QueryResult;
|
||||
import org.oscim.utils.LineClipper;
|
||||
import org.oscim.utils.pool.Inlist;
|
||||
|
||||
/**
|
||||
* @note
|
||||
* 1. The MapWorkers call MapTileLoader.execute() to load a tile.
|
||||
* 2. The tile data will be loaded from current MapDatabase
|
||||
* 3. MapDatabase calls the IMapDataSink functions
|
||||
* implemented by MapTileLoader for WAY and POI items.
|
||||
* 4. these callbacks then call RenderTheme to get the matching style.
|
||||
* 5. RenderTheme calls IRenderCallback functions with style information
|
||||
* 6. Styled items become added to MapTile.layers... roughly
|
||||
*/
|
||||
public class VectorTileLoader extends TileLoader implements IRenderTheme.Callback, ITileDataSink {
|
||||
|
||||
private static final String TAG = VectorTileLoader.class.getName();
|
||||
@ -66,47 +57,41 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
public static final byte STROKE_MIN_ZOOM = 12;
|
||||
public static final byte STROKE_MAX_ZOOM = 17;
|
||||
|
||||
// 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 IRenderTheme renderTheme;
|
||||
private int renderLevels;
|
||||
|
||||
// current TileDataSource used by this MapTileLoader
|
||||
/** current TileDataSource used by this MapTileLoader */
|
||||
private ITileDataSource mTileDataSource;
|
||||
|
||||
// currently processed tile
|
||||
/** currently processed tile */
|
||||
private MapTile mTile;
|
||||
|
||||
// currently processed MapElement
|
||||
/** currently processed MapElement */
|
||||
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 int mDrawingLayer;
|
||||
/** Current layer for adding elements */
|
||||
private int mCurLayer;
|
||||
|
||||
private float mStrokeScale = 1.0f;
|
||||
private float mLatScaleFactor;
|
||||
private float mGroundResolution;
|
||||
|
||||
private Tag mTagName;
|
||||
private Tag mTagHouseNr;
|
||||
/** Line-scale-factor depending on zoom and latitude */
|
||||
private float mLineScale = 1.0f;
|
||||
|
||||
private final LineClipper mClipper;
|
||||
|
||||
private final TagSet mFilteredTags;
|
||||
|
||||
public void setRenderTheme(IRenderTheme theme) {
|
||||
renderTheme = theme;
|
||||
renderLevels = theme.getLevels();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public VectorTileLoader(TileManager tileManager) {
|
||||
super(tileManager);
|
||||
|
||||
mClipper = new LineClipper(0, 0, Tile.SIZE, Tile.SIZE, true);
|
||||
mFilteredTags = new TagSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -115,31 +100,22 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeJob(MapTile mapTile) {
|
||||
public boolean executeJob(MapTile tile) {
|
||||
|
||||
if (mTileDataSource == null)
|
||||
return false;
|
||||
|
||||
mTile = mapTile;
|
||||
|
||||
if (mTile.layers != null) {
|
||||
// should be fixed now.
|
||||
Log.d(TAG, "BUG tile already loaded " + mTile + " " + mTile.getState());
|
||||
mTile = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
setScaleStrokeWidth(mTile.zoomLevel);
|
||||
|
||||
// account for area changes with latitude
|
||||
double latitude = MercatorProjection.toLatitude(mTile.y);
|
||||
double lat = MercatorProjection.toLatitude(tile.y);
|
||||
|
||||
mLatScaleFactor = 0.4f + 0.6f * ((float) Math.sin(Math.abs(latitude) * (Math.PI / 180)));
|
||||
mLineScale = (float) Math.pow(STROKE_INCREASE, tile.zoomLevel - STROKE_MIN_ZOOM);
|
||||
if (mLineScale < 1)
|
||||
mLineScale = 1;
|
||||
|
||||
mGroundResolution = (float) (Math.cos(latitude * (Math.PI / 180))
|
||||
* MercatorProjection.EARTH_CIRCUMFERENCE
|
||||
/ ((long) Tile.SIZE << mTile.zoomLevel));
|
||||
// scale line width relative to latitude + PI * thumb
|
||||
mLineScale *= 0.4f + 0.6f * ((float) Math.sin(Math.abs(lat) * (Math.PI / 180)));
|
||||
|
||||
mTile = tile;
|
||||
mTile.layers = new ElementLayers();
|
||||
|
||||
// query database, which calls renderWay and renderPOI
|
||||
@ -159,8 +135,6 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
}
|
||||
}
|
||||
|
||||
Tag[] mFilterTags = new Tag[1];
|
||||
|
||||
private static int getValidLayer(int layer) {
|
||||
if (layer < 0) {
|
||||
return 0;
|
||||
@ -171,19 +145,6 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scale stroke factor for the given zoom level.
|
||||
*
|
||||
* @param zoomLevel
|
||||
* the zoom level for which the scale stroke factor should be
|
||||
* set.
|
||||
*/
|
||||
private void setScaleStrokeWidth(byte zoomLevel) {
|
||||
mStrokeScale = (float) Math.pow(STROKE_INCREASE, zoomLevel - STROKE_MIN_ZOOM);
|
||||
if (mStrokeScale < 1)
|
||||
mStrokeScale = 1;
|
||||
}
|
||||
|
||||
public void setTileDataSource(ITileDataSource mapDatabase) {
|
||||
if (mTileDataSource != null)
|
||||
mTileDataSource.destroy();
|
||||
@ -191,52 +152,47 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
mTileDataSource = mapDatabase;
|
||||
}
|
||||
|
||||
public ITileDataSource getMapDatabase() {
|
||||
return mTileDataSource;
|
||||
}
|
||||
static class TagReplacement {
|
||||
public TagReplacement(String key) {
|
||||
this.key = key;
|
||||
this.tag = new Tag(key, null);
|
||||
}
|
||||
|
||||
private boolean mRenderBuildingModel;
|
||||
String key;
|
||||
Tag tag;
|
||||
}
|
||||
|
||||
// Replace tags that should only be matched by key in RenderTheme
|
||||
// to avoid caching RenderInstructions for each way of the same type
|
||||
// only with different name.
|
||||
// Maybe this should be done within RenderTheme, also allowing
|
||||
// to set these replacement rules in theme file.
|
||||
private boolean filterTags(TagSet in) {
|
||||
mRenderBuildingModel = false;
|
||||
Tag[] tags = in.tags;
|
||||
private static final TagReplacement[] mTagReplacement = {
|
||||
new TagReplacement(Tag.KEY_NAME),
|
||||
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++) {
|
||||
String key = tags[i].key;
|
||||
if (key == Tag.KEY_NAME) {
|
||||
if (tags[i].value != null) {
|
||||
mTagName = tags[i];
|
||||
tags[i] = mTagEmptyName;
|
||||
}
|
||||
} else if (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) {
|
||||
try {
|
||||
mElement.height = Integer.parseInt(tags[i].value);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
else if (key == Tag.KEY_MIN_HEIGHT) {
|
||||
try {
|
||||
mElement.minHeight = Integer.parseInt(tags[i].value);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
private boolean filterTags(TagSet tagSet) {
|
||||
Tag[] tags = tagSet.tags;
|
||||
|
||||
mFilteredTags.clear();
|
||||
|
||||
O: for (int i = 0, n = tagSet.numTags; i < n; i++) {
|
||||
Tag t = tags[i];
|
||||
|
||||
for (TagReplacement replacement : mTagReplacement) {
|
||||
if (t.key == replacement.key) {
|
||||
mFilteredTags.add(replacement.tag);
|
||||
continue O;
|
||||
}
|
||||
}
|
||||
|
||||
mFilteredTags.add(t);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -250,21 +206,22 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
// remove tags that should not be cached in Rendertheme
|
||||
filterTags(element.tags);
|
||||
|
||||
// get render instructions
|
||||
RenderInstruction[] ri = renderTheme.matchElement(element, mTile.zoomLevel);
|
||||
|
||||
if (ri != null)
|
||||
renderNode(ri);
|
||||
// get and apply render instructions
|
||||
renderNode(renderTheme.matchElement(element.type, mFilteredTags, mTile.zoomLevel));
|
||||
} else {
|
||||
|
||||
// replace tags that should not be cached in Rendertheme (e.g. name)
|
||||
if (!filterTags(element.tags))
|
||||
return;
|
||||
|
||||
mDrawingLayer = getValidLayer(element.layer) * renderLevels;
|
||||
mCurLayer = getValidLayer(element.layer) * renderLevels;
|
||||
|
||||
RenderInstruction[] ri = renderTheme.matchElement(element, mTile.zoomLevel);
|
||||
renderWay(ri);
|
||||
// get and apply render instructions
|
||||
renderWay(renderTheme.matchElement(element.type, mFilteredTags, mTile.zoomLevel));
|
||||
|
||||
//boolean closed = element.type == GeometryType.POLY;
|
||||
//if (debug.debugTheme && ri == null)
|
||||
// debugUnmatched(closed, element.tags);
|
||||
|
||||
mCurLineLayer = null;
|
||||
}
|
||||
@ -272,6 +229,18 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
mElement = null;
|
||||
}
|
||||
|
||||
//private void debugUnmatched(boolean closed, TagSet tags) {
|
||||
// Log.d(TAG, "DBG way not matched: " + closed + " "
|
||||
// + Arrays.deepToString(tags));
|
||||
//
|
||||
// mTagName = new Tag("name", tags[0].key + ":"
|
||||
// + tags[0].value, false);
|
||||
//
|
||||
// mElement.tags = closed ? debugTagArea : debugTagWay;
|
||||
// RenderInstruction[] ri = renderTheme.matchElement(mElement, mTile.zoomLevel);
|
||||
// renderWay(ri);
|
||||
//}
|
||||
|
||||
private void renderWay(RenderInstruction[] ri) {
|
||||
if (ri == null)
|
||||
return;
|
||||
@ -289,15 +258,13 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
}
|
||||
|
||||
private void clearState() {
|
||||
mTagName = null;
|
||||
mTagHouseNr = null;
|
||||
mCurLineLayer = null;
|
||||
}
|
||||
|
||||
// ----------------- RenderThemeCallback -----------------
|
||||
/*** RenderThemeCallback ***/
|
||||
@Override
|
||||
public void renderWay(Line line, int level) {
|
||||
int numLayer = mDrawingLayer + level;
|
||||
int numLayer = mCurLayer + level;
|
||||
|
||||
if (line.stipple == 0) {
|
||||
if (line.outline && mCurLineLayer == null) {
|
||||
@ -313,11 +280,10 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
if (lineLayer.line == null) {
|
||||
lineLayer.line = line;
|
||||
|
||||
float w = line.width * 0.8f;
|
||||
if (!line.fixed) {
|
||||
w *= mStrokeScale;
|
||||
w *= mLatScaleFactor;
|
||||
}
|
||||
float w = line.width;
|
||||
if (!line.fixed)
|
||||
w *= mLineScale;
|
||||
|
||||
lineLayer.width = w;
|
||||
}
|
||||
|
||||
@ -326,8 +292,7 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
return;
|
||||
}
|
||||
|
||||
lineLayer.addLine(mElement.points, mElement.index,
|
||||
mElement.type == GeometryType.POLY);
|
||||
lineLayer.addLine(mElement);
|
||||
|
||||
// keep reference for outline layer
|
||||
mCurLineLayer = lineLayer;
|
||||
@ -342,85 +307,55 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
lineLayer.line = line;
|
||||
|
||||
float w = line.width;
|
||||
if (!line.fixed) {
|
||||
w *= mStrokeScale;
|
||||
w *= mLatScaleFactor;
|
||||
}
|
||||
if (!line.fixed)
|
||||
w *= mLineScale;
|
||||
|
||||
lineLayer.width = w;
|
||||
}
|
||||
|
||||
lineLayer.addLine(mElement.points, mElement.index);
|
||||
lineLayer.addLine(mElement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderArea(Area area, int level) {
|
||||
int numLayer = mDrawingLayer + level;
|
||||
|
||||
if (mRenderBuildingModel) {
|
||||
//Log.d(TAG, "add buildings: " + mTile + " " + mPriority);
|
||||
if (mTile.layers.extrusionLayers == null)
|
||||
mTile.layers.extrusionLayers = new ExtrusionLayer(0, mGroundResolution);
|
||||
|
||||
((ExtrusionLayer) mTile.layers.extrusionLayers).addBuildings(mElement);
|
||||
|
||||
return;
|
||||
}
|
||||
int numLayer = mCurLayer + level;
|
||||
|
||||
PolygonLayer layer = mTile.layers.getPolygonLayer(numLayer);
|
||||
|
||||
if (layer == null)
|
||||
return;
|
||||
|
||||
//if (layer.area == null)
|
||||
layer.area = area;
|
||||
|
||||
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
|
||||
public void renderAreaText(Text text) {
|
||||
// TODO place somewhere on polygon
|
||||
|
||||
String value = textValueForKey(text);
|
||||
String value = mElement.tags.getValue(text.textKey);
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
float x = mElement.points[0];
|
||||
float y = mElement.points[1];
|
||||
|
||||
mTile.addLabel(TextItem.pool.get().set(x, y, value, text));
|
||||
PointF p = mElement.getPoint(0);
|
||||
mTile.addLabel(TextItem.pool.get().set(p.x, p.y, value, text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderPointText(Text text) {
|
||||
String value = textValueForKey(text);
|
||||
String value = mElement.tags.getValue(text.textKey);
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
for (int i = 0, n = mElement.index[0]; i < n; i += 2) {
|
||||
float x = mElement.points[i];
|
||||
float y = mElement.points[i + 1];
|
||||
mTile.addLabel(TextItem.pool.get().set(x, y, value, text));
|
||||
for (int i = 0, n = mElement.getNumPoints(); i < n; i++) {
|
||||
PointF p = mElement.getPoint(i);
|
||||
mTile.addLabel(TextItem.pool.get().set(p.x, p.y, value, text));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderWayText(Text text) {
|
||||
String value = textValueForKey(text);
|
||||
String value = mElement.tags.getValue(text.textKey);
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
@ -436,8 +371,26 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
}
|
||||
}
|
||||
|
||||
Tag TREE_TAG = new Tag("natural", "tree");
|
||||
|
||||
@Override
|
||||
public void renderPointCircle(Circle circle, int level) {
|
||||
|
||||
if (mElement.tags.contains(TREE_TAG))
|
||||
|
||||
for (int i = 0, n = mElement.getNumPoints(); i < n; i++) {
|
||||
PointF p = mElement.getPoint(i);
|
||||
|
||||
SymbolItem it = SymbolItem.pool.get();
|
||||
//it.set(p.x, p.y, null, true);
|
||||
|
||||
it.x = p.x;
|
||||
it.y = p.y;
|
||||
it.tag = mElement.tags.get(TREE_TAG.key);
|
||||
|
||||
mTile.addSymbol(it);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -446,13 +399,13 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
Log.d(TAG, "missing symbol for " + mElement.tags.asString());
|
||||
return;
|
||||
}
|
||||
SymbolItem it = SymbolItem.pool.get();
|
||||
it.x = mElement.points[0];
|
||||
it.y = mElement.points[1];
|
||||
it.texRegion = symbol.texture;
|
||||
it.billboard = true;
|
||||
for (int i = 0, n = mElement.getNumPoints(); i < n; i++) {
|
||||
PointF p = mElement.getPoint(i);
|
||||
|
||||
mTile.symbols = Inlist.push(mTile.symbols, it);
|
||||
SymbolItem it = SymbolItem.pool.get();
|
||||
it.set(p.x, p.y, symbol.texture, true);
|
||||
mTile.addSymbol(it);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -463,4 +416,30 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
|
||||
public void renderWaySymbol(LineSymbol symbol) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderExtrusion(Extrusion extrusion, int level) {
|
||||
|
||||
int height = 0;
|
||||
int minHeight = 0;
|
||||
|
||||
String v = mElement.tags.getValue(Tag.KEY_HEIGHT);
|
||||
if (v != null)
|
||||
height = Integer.parseInt(v);
|
||||
v = mElement.tags.getValue(Tag.KEY_MIN_HEIGHT);
|
||||
if (v != null)
|
||||
minHeight = Integer.parseInt(v);
|
||||
|
||||
ExtrusionLayer l = (ExtrusionLayer) mTile.layers.extrusionLayers;
|
||||
|
||||
if (l == null) {
|
||||
double lat = MercatorProjection.toLatitude(mTile.y);
|
||||
float groundScale = (float) (Math.cos(lat * (Math.PI / 180))
|
||||
* MercatorProjection.EARTH_CIRCUMFERENCE
|
||||
/ ((long) Tile.SIZE << mTile.zoomLevel));
|
||||
|
||||
mTile.layers.extrusionLayers = l = new ExtrusionLayer(0, groundScale);
|
||||
}
|
||||
l.add(mElement, height, minHeight);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user