serious refactor: TileLoader:
- no more duplication of TileLoaders for GWT -> - decouple loadTile() from TileDataSource completed() call - all TileDataSource MUST call completed(success) in any case now
This commit is contained in:
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,6 +513,7 @@ public class TileManager {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!success || tile.state == CANCEL) {
|
||||
log.debug("failed loading: {}", tile);
|
||||
tile.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user