diff --git a/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/layers/tile/TileLoader.java b/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/layers/tile/TileLoader.java index 561fe5f1..7e82c16f 100644 --- a/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/layers/tile/TileLoader.java +++ b/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/layers/tile/TileLoader.java @@ -14,10 +14,17 @@ */ package org.oscim.layers.tile; +import static org.oscim.tiling.ITileDataSink.QueryResult.FAILED; +import static org.oscim.tiling.ITileDataSink.QueryResult.SUCCESS; + +import org.oscim.backend.canvas.Bitmap; +import org.oscim.core.MapElement; +import org.oscim.tiling.ITileDataSink; + import com.badlogic.gdx.Gdx; import com.badlogic.gdx.utils.Timer; -public abstract class TileLoader { +public abstract class TileLoader implements ITileDataSink { private final TileManager mTileManager; private Timer mTimer; @@ -31,7 +38,7 @@ public abstract class TileLoader { public abstract void cleanup(); - protected abstract boolean executeJob(MapTile tile); + protected abstract boolean loadTile(MapTile tile); boolean isInterrupted; @@ -70,48 +77,65 @@ public abstract class TileLoader { mPausing = false; } - boolean mWorking; + protected boolean mWorking; + protected MapTile mTile; public void go() { - if (mWorking) { + if (mWorking) return; - } - MapTile tile = mTileManager.getTileJob(); + mTile = mTileManager.getTileJob(); - if (tile == null) + if (mTile == null) return; try { - executeJob(tile); - + loadTile(mTile); mWorking = true; - } catch (Exception e) { e.printStackTrace(); - - tile.clear(); - jobCompleted(tile, false); + completed(FAILED); } } - public void jobCompleted(MapTile tile, boolean success) { - if (isInterrupted) - success = false; + /** + * Callback to be called by TileDataSource when finished + * loading or on failure. MUST BE CALLED IN ANY CASE! + */ + @Override + public void completed(QueryResult result) { + boolean success = (result == SUCCESS) && !isInterrupted; - mTileManager.jobCompleted(tile, success); + mTileManager.jobCompleted(mTile, success); + mTile = null; mWorking = false; - if (!mPausing && mTileManager.hasTileJobs()) { + if (mPausing || !mTileManager.hasTileJobs()) + return; - Gdx.app.postRunnable(new Runnable() { - - @Override - public void run() { - go(); - } - }); - } + Gdx.app.postRunnable(new Runnable() { + @Override + public void run() { + go(); + } + }); } + + /** + * Called by TileDataSource + */ + @Override + public void process(MapElement element) { + + } + + /** + * Called by TileDataSource + */ + @Override + public void setTileImage(Bitmap bitmap) { + + } + } diff --git a/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/layers/tile/bitmap/BitmapTileLoader.java b/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/layers/tile/bitmap/BitmapTileLoader.java deleted file mode 100644 index 035257c9..00000000 --- a/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/layers/tile/bitmap/BitmapTileLoader.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.oscim.layers.tile.bitmap; - -import static org.oscim.layers.tile.MapTile.State.CANCEL; - -import org.oscim.backend.canvas.Bitmap; -import org.oscim.core.MapElement; -import org.oscim.core.Tile; -import org.oscim.layers.tile.MapTile; -import org.oscim.layers.tile.TileLoader; -import org.oscim.layers.tile.TileManager; -import org.oscim.renderer.elements.BitmapLayer; -import org.oscim.renderer.elements.ElementLayers; -import org.oscim.tiling.ITileDataSink; -import org.oscim.tiling.ITileDataSource; -import org.oscim.tiling.ITileDataSource.QueryResult; -import org.oscim.tiling.TileSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BitmapTileLoader extends TileLoader implements ITileDataSink { - - protected static final Logger log = LoggerFactory.getLogger(BitmapTileLoader.class); - - private final ITileDataSource mTileDataSource; - private MapTile mTile; - - public BitmapTileLoader(TileManager tileManager, TileSource tileSource) { - super(tileManager); - mTileDataSource = tileSource.getDataSource(); - } - - @Override - public void cleanup() { - mTile = null; - } - - @Override - protected boolean executeJob(MapTile tile) { - mTile = tile; - //QueryResult result = null; - //try { - if (mTileDataSource.executeQuery(tile, this) != QueryResult.SUCCESS) { - return false; - } - //} - // catch (CancellationException e) { - // log.debug("{} was canceled", mTile); - // } catch (Exception e) { - // log.debug("{} {}", mTile, e.getMessage()); - // } finally { - // mTile = null; - // } - return true; - //return result == QueryResult.SUCCESS; - } - - @Override - public void setTileImage(Bitmap bitmap) { - if (isCanceled() || mTile.state(CANCEL)) - return; - //throw new CancellationException(); - - BitmapLayer l = new BitmapLayer(false); - l.setBitmap(bitmap, Tile.SIZE, Tile.SIZE); - mTile.layers = new ElementLayers(); - mTile.layers.setTextureLayers(l); - } - - @Override - public void process(MapElement element) { - - } - - @Override - public void completed(boolean success) { - jobCompleted(mTile, success); - mTile = null; - } -} diff --git a/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/layers/tile/vector/VectorTileLoader.java b/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/layers/tile/vector/VectorTileLoader.java deleted file mode 100644 index e6ca50a1..00000000 --- a/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/layers/tile/vector/VectorTileLoader.java +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright 2012, 2013 Hannes Janetzek - * - * 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.layers.tile.vector; - -import org.oscim.backend.canvas.Bitmap; -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; -import org.oscim.layers.tile.MapTile; -import org.oscim.layers.tile.TileLoader; -import org.oscim.layers.tile.TileManager; -import org.oscim.renderer.elements.ElementLayers; -import org.oscim.renderer.elements.ExtrusionLayer; -import org.oscim.renderer.elements.LineLayer; -import org.oscim.renderer.elements.LineTexLayer; -import org.oscim.renderer.elements.MeshLayer; -import org.oscim.renderer.elements.PolygonLayer; -import org.oscim.renderer.elements.SymbolItem; -import org.oscim.renderer.elements.TextItem; -import org.oscim.theme.IRenderTheme; -import org.oscim.theme.styles.Area; -import org.oscim.theme.styles.Circle; -import org.oscim.theme.styles.Extrusion; -import org.oscim.theme.styles.Line; -import org.oscim.theme.styles.LineSymbol; -import org.oscim.theme.styles.RenderStyle; -import org.oscim.theme.styles.Symbol; -import org.oscim.theme.styles.Text; -import org.oscim.tiling.ITileDataSink; -import org.oscim.tiling.ITileDataSource; -import org.oscim.tiling.ITileDataSource.QueryResult; -import org.oscim.utils.geom.LineClipper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class VectorTileLoader extends TileLoader implements IRenderTheme.Callback, ITileDataSink { - - static final Logger log = LoggerFactory.getLogger(VectorTileLoader.class); - - protected static final double STROKE_INCREASE = Math.sqrt(2.5); - protected static final byte LAYERS = 11; - - public static final byte STROKE_MIN_ZOOM = 12; - public static final byte STROKE_MAX_ZOOM = 17; - - protected IRenderTheme renderTheme; - protected int renderLevels; - - /** current TileDataSource used by this MapTileLoader */ - protected ITileDataSource mTileDataSource; - - /** currently processed tile */ - protected MapTile mTile; - - /** currently processed MapElement */ - protected MapElement mElement; - - /** current line layer (will be used for outline layers) */ - protected LineLayer mCurLineLayer; - - /** Current layer for adding elements */ - protected int mCurLayer; - - /** Line-scale-factor depending on zoom and latitude */ - protected float mLineScale = 1.0f; - - protected final LineClipper mClipper; - - protected 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 - public void cleanup() { - mTileDataSource.destroy(); - } - - @Override - public boolean executeJob(MapTile tile) { - - if (mTileDataSource == null) - return false; - - // account for area changes with latitude - double lat = MercatorProjection.toLatitude(tile.y); - - mLineScale = (float) Math.pow(STROKE_INCREASE, tile.zoomLevel - STROKE_MIN_ZOOM); - if (mLineScale < 1) - mLineScale = 1; - - // 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 - // callbacks while processing map tile data. - if (mTileDataSource.executeQuery(mTile, this) != QueryResult.SUCCESS) { - return false; - } - - return true; - } - - public void completed(boolean success) { - jobCompleted(mTile, success); - mTile = null; - } - - protected static int getValidLayer(int layer) { - if (layer < 0) { - return 0; - } else if (layer >= LAYERS) { - return LAYERS - 1; - } else { - return layer; - } - } - - public void setDataSource(ITileDataSource mapDatabase) { - if (mTileDataSource != null) - mTileDataSource.destroy(); - - mTileDataSource = mapDatabase; - } - - static class TagReplacement { - public TagReplacement(String key) { - this.key = key; - this.tag = new Tag(key, null); - } - - String key; - Tag tag; - } - - protected boolean filterTags(TagSet tagSet) { - return true; - } - - @Override - public void process(MapElement element) { - clearState(); - - mElement = element; - - if (element.type == GeometryType.POINT) { - // remove tags that should not be cached in Rendertheme - filterTags(element.tags); - - // 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; - - mCurLayer = getValidLayer(element.layer) * renderLevels; - - // 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; - } - - mElement = null; - } - - //protected void debugUnmatched(boolean closed, TagSet tags) { - // log.debug("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); - //} - - protected void renderWay(RenderStyle[] ri) { - if (ri == null) - return; - - for (int i = 0, n = ri.length; i < n; i++) - ri[i].renderWay(this); - } - - protected void renderNode(RenderStyle[] ri) { - if (ri == null) - return; - - for (int i = 0, n = ri.length; i < n; i++) - ri[i].renderNode(this); - } - - protected void clearState() { - mCurLineLayer = null; - } - - /*** RenderThemeCallback ***/ - @Override - public void renderWay(Line line, int level) { - int numLayer = mCurLayer + level; - - if (line.stipple == 0) { - if (line.outline && mCurLineLayer == null) { - log.error("BUG in theme: line must come before outline!"); - return; - } - - LineLayer ll = mTile.layers.getLineLayer(numLayer); - - if (ll == null) - return; - - if (ll.line == null) { - ll.line = line; - ll.scale = line.fixed ? 1 : mLineScale; - } - - if (line.outline) { - ll.addOutline(mCurLineLayer); - } else { - ll.addLine(mElement); - - // keep reference for outline layer(s) - mCurLineLayer = ll; - } - } else { - LineTexLayer ll = mTile.layers.getLineTexLayer(numLayer); - - if (ll == null) - return; - - if (ll.line == null) { - ll.line = line; - - float w = line.width; - if (!line.fixed) - w *= mLineScale; - - ll.width = w; - } - - ll.addLine(mElement); - } - } - - protected final static boolean USE_MESH_POLY = false; - - @Override - public void renderArea(Area area, int level) { - int numLayer = mCurLayer + level; - if (USE_MESH_POLY) { - MeshLayer l = mTile.layers.getMeshLayer(numLayer); - l.area = area; - l.addMesh(mElement); - } else { - PolygonLayer l = mTile.layers.getPolygonLayer(numLayer); - l.area = area; - l.addPolygon(mElement.points, mElement.index); - } - } - - @Override - public void renderAreaText(Text text) { - // TODO place somewhere on polygon - String value = mElement.tags.getValue(text.textKey); - if (value == null) - return; - - PointF p = mElement.getPoint(0); - mTile.labels.push(TextItem.pool.get().set(p.x, p.y, value, text)); - } - - @Override - public void renderPointText(Text text) { - String value = mElement.tags.getValue(text.textKey); - if (value == null) - return; - - for (int i = 0, n = mElement.getNumPoints(); i < n; i++) { - PointF p = mElement.getPoint(i); - mTile.labels.push(TextItem.pool.get().set(p.x, p.y, value, text)); - } - } - - @Override - public void renderWayText(Text text) { - String value = mElement.tags.getValue(text.textKey); - if (value == null) - return; - - int offset = 0; - for (int i = 0, n = mElement.index.length; i < n; i++) { - int length = mElement.index[i]; - if (length < 4) - break; - - WayDecorator.renderText(mClipper, mElement.points, value, text, - offset, length, mTile); - offset += length; - } - } - - @Override - public void renderPointCircle(Circle circle, int level) { - } - - @Override - public void renderPointSymbol(Symbol symbol) { - if (symbol.texture == null) { - log.debug("missing symbol for " + mElement.tags.toString()); - return; - } - 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, symbol.texture, true); - mTile.symbols.push(it); - } - } - - @Override - public void renderAreaSymbol(Symbol symbol) { - } - - @Override - 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 = mTile.layers.getExtrusionLayers(); - - if (l == null) { - double lat = MercatorProjection.toLatitude(mTile.y); - - float groundScale = (float) MercatorProjection - .groundResolution(lat, 1 << mTile.zoomLevel); - - l = new ExtrusionLayer(0, groundScale, extrusion.colors); - mTile.layers.setExtrusionLayers(l); - } - - /* 12m default */ - if (height == 0) - height = 12 * 100; - - l.add(mElement, height, minHeight); - } - - @Override - public void setTileImage(Bitmap bitmap) { - // TODO Auto-generated method stub - - } -} diff --git a/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/tiling/source/UrlTileDataSource.java b/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/tiling/source/UrlTileDataSource.java index ae334253..22c39a25 100644 --- a/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/tiling/source/UrlTileDataSource.java +++ b/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/tiling/source/UrlTileDataSource.java @@ -14,16 +14,15 @@ */ package org.oscim.tiling.source; +import static org.oscim.tiling.ITileDataSink.QueryResult.FAILED; +import static org.oscim.tiling.ITileDataSink.QueryResult.SUCCESS; + import java.io.IOException; import java.io.InputStream; import org.oscim.layers.tile.MapTile; import org.oscim.tiling.ITileDataSink; import org.oscim.tiling.ITileDataSource; -import org.oscim.tiling.source.ITileDecoder; -import org.oscim.tiling.source.LwHttp; -import org.oscim.tiling.source.UrlTileDataSource; -import org.oscim.tiling.source.UrlTileSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,25 +39,23 @@ public class UrlTileDataSource implements ITileDataSource { mConn = conn; } - UrlTileSource getTileSource(){ + UrlTileSource getTileSource() { return mTileSource; } + private ITileDataSink mSink; private MapTile mTile; @Override - public QueryResult executeQuery(MapTile tile, ITileDataSink sink) { - QueryResult result = QueryResult.SUCCESS; + public void query(MapTile tile, ITileDataSink sink) { mTile = tile; mSink = sink; try { mConn.sendRequest(tile, this); - } catch (Exception e) { + } catch (IOException e) { e.printStackTrace(); - result = QueryResult.FAILED; + sink.completed(FAILED); } - - return result; } public void process(InputStream is) { @@ -72,10 +69,14 @@ public class UrlTileDataSource implements ITileDataSource { } } if (!win) - log.debug(mTile + " failed"); + log.debug("{} failed", mTile); mConn.requestCompleted(); - mSink.completed(win); + + mSink.completed(win ? SUCCESS : FAILED); + + mTile = null; + mSink = null; } @Override diff --git a/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/tiling/source/bitmap/BitmapTileSource.java b/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/tiling/source/bitmap/BitmapTileSource.java index eb665343..65abef20 100644 --- a/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/tiling/source/bitmap/BitmapTileSource.java +++ b/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/tiling/source/bitmap/BitmapTileSource.java @@ -1,5 +1,8 @@ package org.oscim.tiling.source.bitmap; +import static org.oscim.tiling.ITileDataSink.QueryResult.FAILED; +import static org.oscim.tiling.ITileDataSink.QueryResult.SUCCESS; + import org.oscim.gdx.client.GwtBitmap; import org.oscim.layers.tile.MapTile; import org.oscim.tiling.ITileDataSink; @@ -48,7 +51,7 @@ public abstract class BitmapTileSource extends UrlTileSource { } @Override - public QueryResult executeQuery(final MapTile tile, final ITileDataSink sink) { + public void query(final MapTile tile, final ITileDataSink sink) { int pos = mTileSource.formatTilePath(tile, mRequestBuffer, 0); @@ -73,7 +76,7 @@ public abstract class BitmapTileSource extends UrlTileSource { img.addLoadHandler(new LoadHandler() { public void onLoad(LoadEvent event) { sink.setTileImage(new GwtBitmap(img)); - sink.completed(true); + sink.completed(SUCCESS); } }); @@ -81,11 +84,10 @@ public abstract class BitmapTileSource extends UrlTileSource { @Override public void onError(ErrorEvent event) { - sink.completed(false); + sink.completed(FAILED); RootPanel.get().remove(img); } }); - return QueryResult.SUCCESS; } @Override diff --git a/vtm-jeo/src/org/oscim/layers/JeoTileLayer.java b/vtm-jeo/src/org/oscim/layers/JeoTileLayer.java index f9162dc9..31831d16 100644 --- a/vtm-jeo/src/org/oscim/layers/JeoTileLayer.java +++ b/vtm-jeo/src/org/oscim/layers/JeoTileLayer.java @@ -24,7 +24,7 @@ public class JeoTileLayer extends BitmapTileLayer { } @Override - protected boolean executeJob(MapTile tile) { + protected boolean loadTile(MapTile tile) { // TODO Auto-generated method stub return false; } diff --git a/vtm-jeo/src/org/oscim/layers/JeoTileSource.java b/vtm-jeo/src/org/oscim/layers/JeoTileSource.java index 0648e10c..87d8381a 100644 --- a/vtm-jeo/src/org/oscim/layers/JeoTileSource.java +++ b/vtm-jeo/src/org/oscim/layers/JeoTileSource.java @@ -1,5 +1,9 @@ package org.oscim.layers; +import static org.oscim.tiling.ITileDataSink.QueryResult.FAILED; +import static org.oscim.tiling.ITileDataSink.QueryResult.SUCCESS; +import static org.oscim.tiling.ITileDataSink.QueryResult.TILE_NOT_FOUND; + import java.io.ByteArrayInputStream; import java.io.IOException; @@ -32,7 +36,7 @@ public class JeoTileSource extends TileSource { return new ITileDataSource() { @Override - public QueryResult executeQuery(MapTile tile, ITileDataSink sink) { + public void query(MapTile tile, ITileDataSink sink) { log.debug("query {}", tile); try { Tile t = mTileDataset.read(tile.zoomLevel, tile.tileX, @@ -40,20 +44,20 @@ public class JeoTileSource extends TileSource { (1 << tile.zoomLevel) - 1 - tile.tileY); if (t == null) { log.debug("not found {}", tile); - return QueryResult.TILE_NOT_FOUND; + sink.completed(TILE_NOT_FOUND); + return; } Bitmap b = CanvasAdapter.g.decodeBitmap(new ByteArrayInputStream(t.getData())); sink.setTileImage(b); log.debug("success {}", tile); - - return QueryResult.SUCCESS; + sink.completed(SUCCESS); + return; } catch (IOException e) { e.printStackTrace(); } log.debug("fail {}", tile); - - return QueryResult.FAILED; + sink.completed(FAILED); } @Override diff --git a/vtm/src/org/oscim/layers/tile/TileLoader.java b/vtm/src/org/oscim/layers/tile/TileLoader.java index 8539b29d..d44305a6 100644 --- a/vtm/src/org/oscim/layers/tile/TileLoader.java +++ b/vtm/src/org/oscim/layers/tile/TileLoader.java @@ -16,23 +16,30 @@ */ package org.oscim.layers.tile; +import static org.oscim.tiling.ITileDataSink.QueryResult.FAILED; +import static org.oscim.tiling.ITileDataSink.QueryResult.SUCCESS; + +import org.oscim.backend.canvas.Bitmap; +import org.oscim.core.MapElement; +import org.oscim.tiling.ITileDataSink; import org.oscim.utils.PausableThread; -public abstract class TileLoader extends PausableThread { +public abstract class TileLoader extends PausableThread implements ITileDataSink { private static int id; private final String THREAD_NAME; private final TileManager mTileManager; + /** currently processed tile */ + protected MapTile mTile; + public TileLoader(TileManager tileManager) { super(); mTileManager = tileManager; THREAD_NAME = "TileLoader" + (id++); } - public abstract void cleanup(); - - protected abstract boolean executeJob(MapTile tile); + protected abstract boolean loadTile(MapTile tile); public void go() { synchronized (this) { @@ -42,29 +49,17 @@ public abstract class TileLoader extends PausableThread { @Override protected void doWork() { + mTile = mTileManager.getTileJob(); - MapTile tile = mTileManager.getTileJob(); - - if (tile == null) + if (mTile == null) return; - boolean success = false; - try { - success = executeJob(tile); + loadTile(mTile); } catch (Exception e) { e.printStackTrace(); - success = false; + completed(FAILED); } - - if (isInterrupted()) - success = false; - - mTileManager.jobCompleted(tile, success); - } - - public void jobCompleted(MapTile tile, boolean success) { - } @Override @@ -81,4 +76,34 @@ public abstract class TileLoader extends PausableThread { protected boolean hasWork() { return mTileManager.hasTileJobs(); } + + public abstract void cleanup(); + + /** + * Callback to be called by TileDataSource when finished + * loading or on failure. MUST BE CALLED IN ANY CASE! + */ + @Override + public void completed(QueryResult result) { + boolean success = (result == SUCCESS) && !isInterrupted(); + + mTileManager.jobCompleted(mTile, success); + mTile = null; + } + + /** + * Called by TileDataSource + */ + @Override + public void process(MapElement element) { + + } + + /** + * Called by TileDataSource + */ + @Override + public void setTileImage(Bitmap bitmap) { + + } } diff --git a/vtm/src/org/oscim/layers/tile/TileManager.java b/vtm/src/org/oscim/layers/tile/TileManager.java index 0fce9409..0a088d78 100644 --- a/vtm/src/org/oscim/layers/tile/TileManager.java +++ b/vtm/src/org/oscim/layers/tile/TileManager.java @@ -513,6 +513,7 @@ public class TileManager { @Override public void run() { if (!success || tile.state == CANCEL) { + log.debug("failed loading: {}", tile); tile.clear(); return; } diff --git a/vtm/src/org/oscim/layers/tile/bitmap/BitmapTileLoader.java b/vtm/src/org/oscim/layers/tile/bitmap/BitmapTileLoader.java index 74ff4c13..2800bc5c 100644 --- a/vtm/src/org/oscim/layers/tile/bitmap/BitmapTileLoader.java +++ b/vtm/src/org/oscim/layers/tile/bitmap/BitmapTileLoader.java @@ -1,3 +1,19 @@ +/* + * Copyright 2013 Hannes Janetzek + * + * 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.layers.tile.bitmap; import static org.oscim.layers.tile.MapTile.State.CANCEL; @@ -5,26 +21,22 @@ import static org.oscim.layers.tile.MapTile.State.CANCEL; import java.util.concurrent.CancellationException; import org.oscim.backend.canvas.Bitmap; -import org.oscim.core.MapElement; import org.oscim.core.Tile; import org.oscim.layers.tile.MapTile; import org.oscim.layers.tile.TileLoader; import org.oscim.layers.tile.TileManager; import org.oscim.renderer.elements.BitmapLayer; import org.oscim.renderer.elements.ElementLayers; -import org.oscim.tiling.ITileDataSink; import org.oscim.tiling.ITileDataSource; -import org.oscim.tiling.ITileDataSource.QueryResult; import org.oscim.tiling.TileSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class BitmapTileLoader extends TileLoader implements ITileDataSink { +public class BitmapTileLoader extends TileLoader { protected static final Logger log = LoggerFactory.getLogger(BitmapTileLoader.class); private final ITileDataSource mTileDataSource; - private MapTile mTile; public BitmapTileLoader(TileManager tileManager, TileSource tileSource) { super(tileManager); @@ -32,24 +44,17 @@ public class BitmapTileLoader extends TileLoader implements ITileDataSink { } @Override - public void cleanup() { - mTile = null; - } - - @Override - protected boolean executeJob(MapTile tile) { - mTile = tile; - QueryResult result = null; + protected boolean loadTile(MapTile tile) { try { - result = mTileDataSource.executeQuery(tile, this); + mTileDataSource.query(tile, this); } catch (CancellationException e) { - log.debug("{} was canceled", mTile); + log.debug("{} was canceled", tile); + return false; } catch (Exception e) { - log.debug("{} {}", mTile, e.getMessage()); - } finally { - mTile = null; + log.debug("{} {}", tile, e.getMessage()); + return false; } - return result == QueryResult.SUCCESS; + return true; } @Override @@ -64,12 +69,6 @@ public class BitmapTileLoader extends TileLoader implements ITileDataSink { } @Override - public void process(MapElement element) { - - } - - @Override - public void completed(boolean success) { - + public void cleanup() { } } diff --git a/vtm/src/org/oscim/layers/tile/example/TestTileLayer.java b/vtm/src/org/oscim/layers/tile/example/TestTileLayer.java index aa90fb01..bb38c7af 100644 --- a/vtm/src/org/oscim/layers/tile/example/TestTileLayer.java +++ b/vtm/src/org/oscim/layers/tile/example/TestTileLayer.java @@ -55,7 +55,7 @@ public class TestTileLayer extends TileLayer { Line mLineStyle = new Line(Color.BLUE, 2f, Cap.ROUND); @Override - public boolean executeJob(MapTile tile) { + public boolean loadTile(MapTile tile) { log.debug("load tile " + tile); tile.layers = new ElementLayers(); diff --git a/vtm/src/org/oscim/layers/tile/vector/VectorTileLoader.java b/vtm/src/org/oscim/layers/tile/vector/VectorTileLoader.java index 55b6875b..fd50be23 100644 --- a/vtm/src/org/oscim/layers/tile/vector/VectorTileLoader.java +++ b/vtm/src/org/oscim/layers/tile/vector/VectorTileLoader.java @@ -48,14 +48,11 @@ import org.oscim.theme.styles.LineSymbol; import org.oscim.theme.styles.RenderStyle; import org.oscim.theme.styles.Symbol; import org.oscim.theme.styles.Text; -import org.oscim.tiling.ITileDataSink; import org.oscim.tiling.ITileDataSource; -import org.oscim.tiling.ITileDataSource.QueryResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class VectorTileLoader extends TileLoader implements IRenderTheme.Callback, - ITileDataSink { +public class VectorTileLoader extends TileLoader implements IRenderTheme.Callback { static final Logger log = LoggerFactory.getLogger(VectorTileLoader.class); @@ -71,9 +68,6 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac /** current TileDataSource used by this MapTileLoader */ protected ITileDataSource mTileDataSource; - /** currently processed tile */ - protected MapTile mTile; - /** currently processed MapElement */ protected MapElement mElement; @@ -106,7 +100,7 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac } @Override - public boolean executeJob(MapTile tile) { + public boolean loadTile(MapTile tile) { if (mTileDataSource == null) { log.error("no tile source is set"); @@ -118,31 +112,34 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac return false; } - // account for area changes with latitude + /* account for area changes with latitude */ double lat = MercatorProjection.toLatitude(tile.y); - mLineScale = (float) Math.pow(STROKE_INCREASE, tile.zoomLevel - STROKE_MIN_ZOOM); if (mLineScale < 1) mLineScale = 1; - // 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))); - mTile = tile; - mTile.layers = new ElementLayers(); - QueryResult result = null; + tile.layers = new ElementLayers(); + try { - // query database, which calls 'process' callback - result = mTileDataSource.executeQuery(mTile, this); + /* query data source, which calls process() callback */ + mTileDataSource.query(tile, this); } catch (CancellationException e) { - log.debug("{} was canceled", mTile); + log.debug("{} was canceled", tile); + return false; } catch (Exception e) { - log.debug("{} {}", mTile, e.getMessage()); - } finally { - mTile = null; - clearState(); + log.debug("{} {}", tile, e.getMessage()); + return false; } - return (result == QueryResult.SUCCESS); + return true; + } + + @Override + public void completed(QueryResult result) { + super.completed(result); + clearState(); } protected static int getValidLayer(int layer) { @@ -254,8 +251,6 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac public void renderWay(Line line, int level) { int numLayer = mCurLayer + level; - // line = line.getCurrent(); - if (line.stipple == 0) { if (line.outline && mCurLineLayer == null) { log.debug("missing line for outline! " + mElement.tags @@ -395,7 +390,6 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac @Override public void renderExtrusion(Extrusion extrusion, int level) { - int height = 0; int minHeight = 0; @@ -424,13 +418,6 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac l.add(mElement, height, minHeight); } - /** - * used for event-driven loading by html backend - */ - @Override - public void completed(boolean success) { - } - @Override public void setTileImage(Bitmap bitmap) { diff --git a/vtm/src/org/oscim/tiling/ITileDataSink.java b/vtm/src/org/oscim/tiling/ITileDataSink.java index f81c1dd3..3bfbec5a 100644 --- a/vtm/src/org/oscim/tiling/ITileDataSink.java +++ b/vtm/src/org/oscim/tiling/ITileDataSink.java @@ -23,7 +23,7 @@ import org.oscim.core.MapElement; * MapDatabase callback (implemented by MapTileLoader) * . * NOTE: MapElement passed belong to the caller! i.e. dont hold - * references to its arrays after callback function returns. + * references to any of its data after callback function returns. */ public interface ITileDataSink { @@ -31,5 +31,12 @@ public interface ITileDataSink { void setTileImage(Bitmap bitmap); - void completed(boolean success); + void completed(QueryResult result); + + public static enum QueryResult { + SUCCESS, + FAILED, + TILE_NOT_FOUND, + DELAYED, + } } diff --git a/vtm/src/org/oscim/tiling/ITileDataSource.java b/vtm/src/org/oscim/tiling/ITileDataSource.java index 161cea45..fecc126b 100644 --- a/vtm/src/org/oscim/tiling/ITileDataSource.java +++ b/vtm/src/org/oscim/tiling/ITileDataSource.java @@ -19,7 +19,6 @@ package org.oscim.tiling; import org.oscim.layers.tile.MapTile; - /** * * @@ -33,17 +32,9 @@ public interface ITileDataSource { * the tile to read. * @param mapDataSink * the callback which handles the extracted map elements. - * @return true if successful */ - abstract QueryResult executeQuery(MapTile tile, - ITileDataSink mapDataSink); + abstract void query(MapTile tile, ITileDataSink mapDataSink); abstract void destroy(); - public static enum QueryResult { - SUCCESS, - FAILED, - TILE_NOT_FOUND, - DELAYED, - } } diff --git a/vtm/src/org/oscim/tiling/source/UrlTileDataSource.java b/vtm/src/org/oscim/tiling/source/UrlTileDataSource.java index f2fe87ac..f26c90c0 100644 --- a/vtm/src/org/oscim/tiling/source/UrlTileDataSource.java +++ b/vtm/src/org/oscim/tiling/source/UrlTileDataSource.java @@ -16,6 +16,9 @@ */ package org.oscim.tiling.source; +import static org.oscim.tiling.ITileDataSink.QueryResult.FAILED; +import static org.oscim.tiling.ITileDataSink.QueryResult.SUCCESS; + import java.io.IOException; import java.io.InputStream; import java.net.SocketException; @@ -24,10 +27,10 @@ import java.net.UnknownHostException; import org.oscim.layers.tile.MapTile; import org.oscim.tiling.ITileCache; -import org.oscim.tiling.ITileDataSink; -import org.oscim.tiling.ITileDataSource; import org.oscim.tiling.ITileCache.TileReader; import org.oscim.tiling.ITileCache.TileWriter; +import org.oscim.tiling.ITileDataSink; +import org.oscim.tiling.ITileDataSource; import org.oscim.utils.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,7 +51,7 @@ public class UrlTileDataSource implements ITileDataSource { } @Override - public QueryResult executeQuery(MapTile tile, ITileDataSink sink) { + public void query(MapTile tile, ITileDataSink sink) { ITileCache cache = mTileSource.tileCache; if (mUseCache) { @@ -56,9 +59,10 @@ public class UrlTileDataSource implements ITileDataSource { if (c != null) { InputStream is = c.getInputStream(); try { - if (mTileDecoder.decode(tile, sink, is)) - return QueryResult.SUCCESS; - + if (mTileDecoder.decode(tile, sink, is)) { + sink.completed(SUCCESS); + return; + } } catch (IOException e) { log.debug("{} Cache read: {}", tile, e); } finally { @@ -95,7 +99,7 @@ public class UrlTileDataSource implements ITileDataSource { if (cacheWriter != null) cacheWriter.complete(success); } - return success ? QueryResult.SUCCESS : QueryResult.FAILED; + sink.completed(success ? SUCCESS : FAILED); } @Override diff --git a/vtm/src/org/oscim/tiling/source/mapfile/MapDatabase.java b/vtm/src/org/oscim/tiling/source/mapfile/MapDatabase.java index c361ebb4..679e5dd2 100644 --- a/vtm/src/org/oscim/tiling/source/mapfile/MapDatabase.java +++ b/vtm/src/org/oscim/tiling/source/mapfile/MapDatabase.java @@ -17,6 +17,9 @@ */ package org.oscim.tiling.source.mapfile; +import static org.oscim.tiling.ITileDataSink.QueryResult.FAILED; +import static org.oscim.tiling.ITileDataSink.QueryResult.SUCCESS; + import java.io.IOException; import java.io.RandomAccessFile; @@ -142,14 +145,13 @@ public class MapDatabase implements ITileDataSource { private final MapFileTileSource mTileSource; - //private int mReductionCnt; - //private int mSkipPoly; - @Override - public QueryResult executeQuery(MapTile tile, ITileDataSink mapDataSink) { + public void query(MapTile tile, ITileDataSink sink) { - if (mTileSource.fileHeader == null) - return QueryResult.FAILED; + if (mTileSource.fileHeader == null) { + sink.completed(FAILED); + return; + } if (mIntBuffer == null) mIntBuffer = new int[MAXIMUM_WAY_NODES_SEQUENCE_LENGTH * 2]; @@ -172,11 +174,6 @@ public class MapDatabase implements ITileDataSource { minLon = (int) (Math.abs(MercatorProjection.toLongitude(tile.x + size) - MercatorProjection.toLongitude(tile.x)) * 1e6) / simplify; - //mReductionCnt = 0; - //mSkipPoly = 0; - - //log.debug("simplify by " + minLat + "/" + minLon); - QueryParameters queryParameters = new QueryParameters(); queryParameters.queryZoomLevel = mTileSource.fileHeader.getQueryZoomLevel(tile.zoomLevel); @@ -189,20 +186,20 @@ public class MapDatabase implements ITileDataSource { log.warn("no sub-file for zoom level: " + queryParameters.queryZoomLevel); - return QueryResult.FAILED; + sink.completed(FAILED); + return; } QueryCalculations.calculateBaseTiles(queryParameters, tile, subFileParameter); QueryCalculations.calculateBlocks(queryParameters, subFileParameter); - processBlocks(mapDataSink, queryParameters, subFileParameter); + processBlocks(sink, queryParameters, subFileParameter); } catch (IOException e) { log.error(e.getMessage()); - return QueryResult.FAILED; + sink.completed(FAILED); + return; } - //log.debug("reduced points " + mReductionCnt + " / polys " + mSkipPoly); - - return QueryResult.SUCCESS; + sink.completed(SUCCESS); } public MapDatabase(MapFileTileSource tileSource) throws IOException { diff --git a/vtm/src/org/oscim/tiling/source/test/TestTileSource.java b/vtm/src/org/oscim/tiling/source/test/TestTileSource.java index 4cfa0925..5a5675db 100644 --- a/vtm/src/org/oscim/tiling/source/test/TestTileSource.java +++ b/vtm/src/org/oscim/tiling/source/test/TestTileSource.java @@ -16,6 +16,8 @@ */ package org.oscim.tiling.source.test; +import static org.oscim.tiling.ITileDataSink.QueryResult.SUCCESS; + import org.oscim.core.MapElement; import org.oscim.core.Tag; import org.oscim.core.Tile; @@ -74,8 +76,7 @@ public class TestTileSource extends TileSource { private boolean renderPlace = false; @Override - public QueryResult executeQuery(MapTile tile, - ITileDataSink mapDataSink) { + public void query(MapTile tile, ITileDataSink sink) { int size = Tile.SIZE; MapElement e = mElem; @@ -107,7 +108,7 @@ public class TestTileSource extends TileSource { e.setLayer(0); e.tags.set(mTags); - mapDataSink.process(e); + sink.process(e); if (renderWays) { e.clear(); @@ -128,7 +129,7 @@ public class TestTileSource extends TileSource { e.addPoint(size / 2, size / 2 + size); // //e.setLayer(mTagsWay, 0); - mapDataSink.process(e); + sink.process(e); e.clear(); // left-top to center @@ -146,7 +147,7 @@ public class TestTileSource extends TileSource { e.setLayer(1); e.tags.set(mTagsWay); - mapDataSink.process(e); + sink.process(e); } if (renderBoundary) { @@ -162,7 +163,7 @@ public class TestTileSource extends TileSource { e.setLayer(1); e.tags.set(mTagsBoundary); - mapDataSink.process(e); + sink.process(e); } if (renderPlace) { @@ -172,12 +173,10 @@ public class TestTileSource extends TileSource { mTagsPlace[1] = new Tag("name", tile.toString()); e.tags.set(mTagsPlace); - mapDataSink.process(e); + sink.process(e); } - mapDataSink.completed(true); - - return QueryResult.SUCCESS; + sink.completed(SUCCESS); } @Override