refactoring of TileLayer, some more

This commit is contained in:
Hannes Janetzek 2013-04-23 01:13:21 +02:00
parent 2bc71090b3
commit 676b994f2d
15 changed files with 409 additions and 378 deletions

View File

@ -15,8 +15,8 @@
package org.oscim.core; package org.oscim.core;
/** /**
* MapElement is created by MapDatabase(s) and passed to TileGenerator * MapElement is created by MapDatabase(s) and passed to MapTileLoader
* via IMapDatabaseCallback.renderElement() TileGenerator processes the * via IMapDatabaseCallback.renderElement() MapTileLoader processes the
* data into MapTile.layers. * data into MapTile.layers.
* ----- * -----
* This is really just a buffer object that belongs to MapDatabase, so * This is really just a buffer object that belongs to MapDatabase, so

View File

@ -32,7 +32,7 @@ public interface IMapDatabase {
* the callback which handles the extracted map elements. * the callback which handles the extracted map elements.
* @return true if successful * @return true if successful
*/ */
public abstract QueryResult executeQuery(MapTile tile, abstract QueryResult executeQuery(MapTile tile,
IMapDatabaseCallback mapDatabaseCallback); IMapDatabaseCallback mapDatabaseCallback);
/** /**
@ -40,12 +40,12 @@ public interface IMapDatabase {
* @throws IllegalStateException * @throws IllegalStateException
* if no map is currently opened. * if no map is currently opened.
*/ */
public abstract MapInfo getMapInfo(); abstract MapInfo getMapInfo();
/** /**
* @return true if a map database is currently opened, false otherwise. * @return true if a map database is currently opened, false otherwise.
*/ */
public abstract boolean isOpen(); abstract boolean isOpen();
/** /**
* Opens MapDatabase * Opens MapDatabase
@ -54,21 +54,21 @@ public interface IMapDatabase {
* the options. * the options.
* @return a OpenResult containing an error message in case of a failure. * @return a OpenResult containing an error message in case of a failure.
*/ */
public abstract OpenResult open(MapOptions options); abstract OpenResult open(MapOptions options);
/** /**
* Closes the map file and destroys all internal caches. Has no effect if no * Closes the map file and destroys all internal caches. Has no effect if no
* map file is currently opened. Should also force to close Socket so that * map file is currently opened. Should also force to close Socket so that
* thread cannot hang in socket.read * thread cannot hang in socket.read
*/ */
public abstract void close(); abstract void close();
public abstract String getMapProjection(); abstract String getMapProjection();
/** /**
* Cancel loading * Cancel loading
*/ */
public abstract void cancel(); abstract void cancel();
public static enum QueryResult { public static enum QueryResult {
SUCCESS, SUCCESS,

View File

@ -18,7 +18,7 @@ import org.oscim.core.MapElement;
/** /**
* MapDatabase callbacks (implemented by TileGenerator) * MapDatabase callbacks (implemented by MapTileLoader)
* ____ * ____
* NOTE: All parameters passed belong to the caller! i.e. dont hold * NOTE: All parameters passed belong to the caller! i.e. dont hold
* references to any arrays after callback function returns. * references to any arrays after callback function returns.

View File

@ -1,26 +0,0 @@
/*
* Copyright 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 <http://www.gnu.org/licenses/>.
*/
package org.oscim.layers.tile;
public interface ITileGenerator {
/**
* Load data for 'tile' and file tile.layers for rendering.
* (executed on MapWorker threads)
*/
public abstract boolean executeJob(MapTile tile);
public abstract void cleanup();
}

View File

@ -21,7 +21,7 @@ import org.oscim.utils.quadtree.QuadTree;
/** /**
* Extends Tile class to hold state and data for concurrent use in * Extends Tile class to hold state and data for concurrent use in
* TileManager (Main Thread), TileGenerator (MapWorker Thread) and * TileManager (Main Thread), TileLoader (Worker Threads) and
* Rendering (GL Thread). * Rendering (GL Thread).
*/ */
public final class MapTile extends Tile { public final class MapTile extends Tile {
@ -30,7 +30,7 @@ public final class MapTile extends Tile {
/** /**
* STATE_LOADING means the tile is about to be loaded / loading. * STATE_LOADING means the tile is about to be loaded / loading.
* it belongs to MapWorker/TileGenerator thread. * it belongs to TileLoader thread.
*/ */
public final static int STATE_LOADING = 1 << 0; public final static int STATE_LOADING = 1 << 0;
@ -66,7 +66,7 @@ public final class MapTile extends Tile {
public float distance; public float distance;
/** /**
* Tile data set by TileGenerator. * Tile data set by TileLoader.
*/ */
public TextItem labels; public TextItem labels;
public Layers layers; public Layers layers;

View File

@ -0,0 +1,231 @@
/*
* Copyright 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 <http://www.gnu.org/licenses/>.
*/
package org.oscim.layers.tile;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import org.oscim.core.GeoPoint;
import org.oscim.core.MapPosition;
import org.oscim.database.IMapDatabase;
import org.oscim.database.IMapDatabase.OpenResult;
import org.oscim.database.MapDatabaseFactory;
import org.oscim.database.MapDatabases;
import org.oscim.database.MapInfo;
import org.oscim.database.MapOptions;
import org.oscim.renderer.GLRenderer;
import org.oscim.theme.ExternalRenderTheme;
import org.oscim.theme.IRenderTheme;
import org.oscim.theme.InternalRenderTheme;
import org.oscim.theme.RenderThemeHandler;
import org.oscim.theme.Theme;
import org.oscim.view.MapView;
import org.xml.sax.SAXException;
import android.util.Log;
public class MapTileLayer extends TileLayer<MapTileLoader> {
private final static String TAG = MapTileLayer.class.getName();
public MapTileLayer(MapView mapView) {
super(mapView, new TileLoader.Factory<MapTileLoader>(){
@Override
public MapTileLoader create(JobQueue q, TileManager tm) {
return new MapTileLoader(q, tm);
}});
}
private MapOptions mMapOptions;
private IMapDatabase mMapDatabase;
private String mRenderTheme;
/**
* Sets the MapDatabase for this MapView.
*
* @param options
* the new MapDatabase options.
* @return true if MapDatabase changed
*/
public boolean setMapDatabase(MapOptions options) {
Log.i(TAG, "setMapDatabase: " + options.db.name());
if (mMapOptions != null && mMapOptions.equals(options))
return true;
pauseLoaders(true);
mJobQueue.clear();
mMapOptions = options;
mMapDatabase = null;
for (int i = 0; i < mNumTileLoader; i++) {
IMapDatabase mapDatabase = MapDatabaseFactory
.createMapDatabase(options.db);
OpenResult result = mapDatabase.open(options);
if (result != OpenResult.SUCCESS) {
Log.d(TAG, "failed open db: " + result.getErrorMessage());
}
mTileLoader.get(i).setMapDatabase(mapDatabase);
// TODO this could be done in a cleaner way..
if (mMapDatabase == null)
mMapDatabase = mapDatabase;
}
if (options.db == MapDatabases.OSCIMAP_READER ||
options.db == MapDatabases.MAP_READER ||
options.db == MapDatabases.TEST_READER)
MapView.enableClosePolygons = true;
else
MapView.enableClosePolygons = false;
clearMap();
resumeLoaders();
return true;
}
public Map<String, String> getMapOptions() {
return mMapOptions;
}
public MapPosition getMapFileCenter() {
if (mMapDatabase == null)
return null;
MapInfo mapInfo = mMapDatabase.getMapInfo();
if (mapInfo == null)
return null;
GeoPoint startPos = mapInfo.startPosition;
if (startPos == null)
startPos = mapInfo.mapCenter;
if (startPos == null)
startPos = new GeoPoint(0, 0);
MapPosition mapPosition = new MapPosition();
mapPosition.setPosition(startPos);
if (mapInfo.startZoomLevel == null)
mapPosition.setZoomLevel(12);
else
mapPosition.setZoomLevel((mapInfo.startZoomLevel).byteValue());
return mapPosition;
}
public String getRenderTheme() {
return mRenderTheme;
}
/**
* Sets the internal theme which is used for rendering the map.
*
* @param internalRenderTheme
* the internal rendering theme.
* @return ...
* @throws IllegalArgumentException
* if the supplied internalRenderTheme is null.
*/
public boolean setRenderTheme(InternalRenderTheme internalRenderTheme) {
if (internalRenderTheme == null) {
throw new IllegalArgumentException("render theme must not be null");
}
if (internalRenderTheme.name() == mRenderTheme)
return true;
boolean ret = setRenderTheme((Theme) internalRenderTheme);
if (ret) {
mRenderTheme = internalRenderTheme.name();
}
clearMap();
return ret;
}
/**
* Sets the theme file which is used for rendering the map.
*
* @param renderThemePath
* the path to the XML file which defines the rendering theme.
* @throws IllegalArgumentException
* if the supplied internalRenderTheme is null.
* @throws FileNotFoundException
* if the supplied file does not exist, is a directory or cannot
* be read.
*/
public void setRenderTheme(String renderThemePath) throws FileNotFoundException {
if (renderThemePath == null) {
throw new IllegalArgumentException("render theme path must not be null");
}
boolean ret = setRenderTheme(new ExternalRenderTheme(renderThemePath));
if (ret) {
mRenderTheme = renderThemePath;
}
clearMap();
}
private boolean setRenderTheme(Theme theme) {
pauseLoaders(true);
InputStream inputStream = null;
try {
inputStream = theme.getRenderThemeAsStream();
IRenderTheme t = RenderThemeHandler.getRenderTheme(inputStream);
t.scaleTextSize(1 + (MapView.dpi / 240 - 1) * 0.5f);
// FIXME !!!
GLRenderer.setRenderTheme(t);
for (MapTileLoader g : mTileLoader)
g.setRenderTheme(t);
return true;
} catch (ParserConfigurationException e) {
Log.e(TAG, e.getMessage());
} catch (SAXException e) {
Log.e(TAG, e.getMessage());
} catch (IOException e) {
Log.e(TAG, e.getMessage());
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
resumeLoaders();
}
return false;
}
}

View File

@ -50,17 +50,17 @@ import android.util.Log;
/** /**
* @note * @note
* 1. The MapWorkers call TileGenerator.execute() to load a tile. * 1. The MapWorkers call MapTileLoader.execute() to load a tile.
* 2. The tile data will be loaded from current MapDatabase * 2. The tile data will be loaded from current MapDatabase
* 3. MapDatabase calls the IMapDatabaseCallback functions * 3. MapDatabase calls the IMapDatabaseCallback functions
* implemented by TileGenerator for WAY and POI items. * implemented by MapTileLoader for WAY and POI items.
* 4. these callbacks then call RenderTheme to get the matching style. * 4. these callbacks then call RenderTheme to get the matching style.
* 5. RenderTheme calls IRenderCallback functions with style information * 5. RenderTheme calls IRenderCallback functions with style information
* 6. Styled items become added to MapTile.layers... roughly * 6. Styled items become added to MapTile.layers... roughly
*/ */
public class TileGenerator extends MapWorker implements IRenderCallback, IMapDatabaseCallback, ITileGenerator { public class MapTileLoader extends TileLoader implements IRenderCallback, IMapDatabaseCallback {
private static final String TAG = TileGenerator.class.getName(); private static final String TAG = MapTileLoader.class.getName();
private static final double STROKE_INCREASE = Math.sqrt(2.2); private static final double STROKE_INCREASE = Math.sqrt(2.2);
private static final byte LAYERS = 11; private static final byte LAYERS = 11;
@ -83,7 +83,7 @@ public class TileGenerator extends MapWorker implements IRenderCallback, IMapDat
private IRenderTheme renderTheme; private IRenderTheme renderTheme;
private int renderLevels; private int renderLevels;
// current MapDatabase used by this TileGenerator // current MapDatabase used by this MapTileLoader
private IMapDatabase mMapDatabase; private IMapDatabase mMapDatabase;
// currently processed tile // currently processed tile
@ -117,8 +117,8 @@ public class TileGenerator extends MapWorker implements IRenderCallback, IMapDat
/** /**
*/ */
public TileGenerator(int id, JobQueue jobQueue, TileManager tileManager) { public MapTileLoader(JobQueue jobQueue, TileManager tileManager) {
super(id, jobQueue, tileManager); super(jobQueue, tileManager);
mClipper = new LineClipper(0, 0, Tile.SIZE, Tile.SIZE, true); mClipper = new LineClipper(0, 0, Tile.SIZE, Tile.SIZE, true);
@ -140,7 +140,7 @@ public class TileGenerator extends MapWorker implements IRenderCallback, IMapDat
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.oscim.layers.tile.ITileGenerator#cleanup() * @see org.oscim.layers.tile.TileLoader#cleanup()
*/ */
@Override @Override
public void cleanup() { public void cleanup() {
@ -148,7 +148,7 @@ public class TileGenerator extends MapWorker implements IRenderCallback, IMapDat
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.oscim.layers.tile.ITileGenerator#executeJob(org.oscim.layers.tile.MapTile) * @see org.oscim.layers.tile.TileLoader#executeJob(org.oscim.layers.tile.MapTile)
*/ */
@Override @Override
public boolean executeJob(MapTile mapTile) { public boolean executeJob(MapTile mapTile) {

View File

@ -0,0 +1,79 @@
/*
* Copyright 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 <http://www.gnu.org/licenses/>.
*/
package org.oscim.layers.tile;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.Tile;
import org.oscim.graphics.Color;
import org.oscim.graphics.Paint.Cap;
import org.oscim.layers.tile.TestTileLayer.TestTileLoader;
import org.oscim.renderer.layer.Layers;
import org.oscim.renderer.layer.LineLayer;
import org.oscim.theme.renderinstruction.Line;
import org.oscim.view.MapView;
import android.util.Log;
public class TestTileLayer extends TileLayer<TestTileLoader> {
final static String TAG = TestTileLayer.class.getName();
public TestTileLayer(MapView mapView) {
// create an TileLayer instance using TestTileLoader as TileLoader
super(mapView, new TileLoader.Factory<TestTileLoader>(){
@Override
public TestTileLoader create(JobQueue q, TileManager tm) {
return new TestTileLoader(q, tm);
}});
}
static class TestTileLoader extends TileLoader {
public TestTileLoader(JobQueue jobQueue, TileManager tileManager) {
super(jobQueue, tileManager);
}
GeometryBuffer mGeom = new GeometryBuffer(128, 16);
Line mLineStyle = new Line(Color.BLUE, 2f, Cap.ROUND);
@Override
public boolean executeJob(MapTile tile) {
Log.d(TAG, "load tile " + tile);
tile.layers = new Layers();
LineLayer ll = tile.layers.getLineLayer(0);
ll.line = mLineStyle;
ll.width = 2;
int m = 20;
int s = Tile.SIZE - m * 2;
GeometryBuffer g = mGeom;
g.clear();
g.startLine();
g.addPoint(m, m);
g.addPoint(m, s);
g.addPoint(s, s);
g.addPoint(s, m);
g.addPoint(m, m);
ll.addLine(g);
return true;
}
@Override
public void cleanup() {
}
}
}

View File

@ -51,13 +51,11 @@ public class TileDistanceSort {
return 0; return 0;
} }
private static void binarySort(MapTile[] a, int lo, int hi, int start) private static void binarySort(MapTile[] a, int lo, int hi, int start) {
{
assert ((lo <= start) && (start <= hi)); assert ((lo <= start) && (start <= hi));
if (start == lo) if (start == lo)
++start; ++start;
for (; start < hi; ++start) for (; start < hi; ++start) {
{
MapTile pivot = a[start]; MapTile pivot = a[start];
int left = lo; int left = lo;
@ -98,8 +96,7 @@ public class TileDistanceSort {
} }
} }
private static int countRunAndMakeAscending(MapTile[] a, int lo, int hi) private static int countRunAndMakeAscending(MapTile[] a, int lo, int hi) {
{
assert (lo < hi); assert (lo < hi);
int runHi = lo + 1; int runHi = lo + 1;
if (runHi == hi) { if (runHi == hi) {
@ -118,8 +115,7 @@ public class TileDistanceSort {
return (runHi - lo); return (runHi - lo);
} }
private static void reverseRange(MapTile[] a, int lo, int hi) private static void reverseRange(MapTile[] a, int lo, int hi) {
{
--hi; --hi;
while (lo < hi) { while (lo < hi) {
MapTile t = a[lo]; MapTile t = a[lo];
@ -127,4 +123,7 @@ public class TileDistanceSort {
a[(hi--)] = t; a[(hi--)] = t;
} }
} }
private TileDistanceSort() {
}
} }

View File

@ -1,54 +0,0 @@
/*
* Copyright 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 <http://www.gnu.org/licenses/>.
*/
package org.oscim.layers.tile;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.Tile;
import org.oscim.graphics.Color;
import org.oscim.graphics.Paint.Cap;
import org.oscim.renderer.layer.LineLayer;
import org.oscim.theme.renderinstruction.Line;
public class TileGeneratorExample implements ITileGenerator {
GeometryBuffer mGeom = new GeometryBuffer(128, 16);
Line mLineStyle = new Line(Color.BLUE, 2f, Cap.ROUND);
@Override
public boolean executeJob(MapTile tile) {
LineLayer ll = tile.layers.getLineLayer(0);
ll.line = mLineStyle;
ll.width = 2;
int m = 20;
int s = Tile.SIZE - m * 2;
GeometryBuffer g = mGeom;
g.clear();
g.startPolygon();
g.addPoint(m, m);
g.addPoint(m, s);
g.addPoint(s, s);
g.addPoint(s, m);
ll.addLine(g);
return true;
}
@Override
public void cleanup() {
}
}

View File

@ -14,58 +14,43 @@
*/ */
package org.oscim.layers.tile; package org.oscim.layers.tile;
import java.io.FileNotFoundException; import java.util.ArrayList;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import org.oscim.core.GeoPoint;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.database.IMapDatabase;
import org.oscim.database.IMapDatabase.OpenResult;
import org.oscim.database.MapDatabaseFactory;
import org.oscim.database.MapDatabases;
import org.oscim.database.MapInfo;
import org.oscim.database.MapOptions;
import org.oscim.layers.Layer; import org.oscim.layers.Layer;
import org.oscim.renderer.GLRenderer;
import org.oscim.theme.ExternalRenderTheme;
import org.oscim.theme.IRenderTheme;
import org.oscim.theme.InternalRenderTheme;
import org.oscim.theme.RenderThemeHandler;
import org.oscim.theme.Theme;
import org.oscim.view.MapView; import org.oscim.view.MapView;
import org.xml.sax.SAXException;
import android.util.Log; public class TileLayer<T extends TileLoader> extends Layer {
//private final static String TAG = TileLayer.class.getName();
public class TileLayer extends Layer {
private final static String TAG = TileLayer.class.getName();
private boolean mClearMap = true; private boolean mClearMap = true;
private final TileManager mTileManager; protected final TileManager mTileManager;
private final JobQueue mJobQueue; protected final JobQueue mJobQueue;
private final int mNumTileWorker = 4; protected final int mNumTileLoader = 4;
private final TileGenerator mTileWorker[]; protected final ArrayList<T> mTileLoader;
public TileLayer(MapView mapView) { public TileLayer(MapView mapView, TileLoader.Factory<T> factory) {
super(mapView); super(mapView);
// TileManager responsible for adding visible tiles
// to load queue and managing in-memory tile cache.
mTileManager = new TileManager(mapView, this); mTileManager = new TileManager(mapView, this);
mJobQueue = new JobQueue(); mJobQueue = new JobQueue();
mTileWorker = new TileGenerator[mNumTileWorker];
TileGenerator.setDebugSettings(mapView.getDebugSettings()); // Instantiate TileLoader threads
mTileLoader = new ArrayList<T>();
for (int i = 0; i < mNumTileWorker; i++) { for (int i = 0; i < mNumTileLoader; i++) {
mTileWorker[i] = new TileGenerator(i, mJobQueue, mTileManager); T tileGenerator = factory.create(mJobQueue, mTileManager);
mTileWorker[i].start(); mTileLoader.add(tileGenerator);
tileGenerator.start();
} }
// RenderLayer is working in GL Thread and actually
// drawing loaded tiles to screen.
mLayer = new TileRenderLayer(mapView, mTileManager); mLayer = new TileRenderLayer(mapView, mTileManager);
} }
@ -80,7 +65,6 @@ public class TileLayer extends Layer {
mTileManager.init(mMapView.getWidth(), mMapView.getHeight()); mTileManager.init(mMapView.getWidth(), mMapView.getHeight());
mClearMap = false; mClearMap = false;
changed = true; changed = true;
Log.d(TAG, "init TileManager ----- ");
} }
if (changed) if (changed)
mTileManager.update(mapPosition); mTileManager.update(mapPosition);
@ -91,7 +75,7 @@ public class TileLayer extends Layer {
mTileManager.destroy(); mTileManager.destroy();
for (TileGenerator tileWorker : mTileWorker) { for (T tileWorker : mTileLoader) {
tileWorker.pause(); tileWorker.pause();
tileWorker.interrupt(); tileWorker.interrupt();
@ -107,192 +91,11 @@ public class TileLayer extends Layer {
} }
} }
private void clearMap() { protected void clearMap() {
// clear tile and overlay data before next draw // clear tile and overlay data before next draw
mClearMap = true; mClearMap = true;
} }
private MapOptions mMapOptions;
private IMapDatabase mMapDatabase;
private String mRenderTheme;
/**
* Sets the MapDatabase for this MapView.
*
* @param options
* the new MapDatabase options.
* @return true if MapDatabase changed
*/
public boolean setMapDatabase(MapOptions options) {
Log.i(TAG, "setMapDatabase: " + options.db.name());
if (mMapOptions != null && mMapOptions.equals(options))
return true;
tileWorkersPause(true);
mJobQueue.clear();
mMapOptions = options;
mMapDatabase = null;
for (int i = 0; i < mNumTileWorker; i++) {
//TileGenerator tileWorker = mTileWorker[i];
IMapDatabase mapDatabase = MapDatabaseFactory
.createMapDatabase(options.db);
OpenResult result = mapDatabase.open(options);
if (result != OpenResult.SUCCESS) {
Log.d(TAG, "failed open db: " + result.getErrorMessage());
}
mTileWorker[i].setMapDatabase(mapDatabase);
//TileGenerator tileGenerator = tileWorker.getTileGenerator();
//tileGenerator.setMapDatabase(mapDatabase);
// TODO this could be done in a cleaner way..
if (mMapDatabase == null)
mMapDatabase = mapDatabase;
}
if (options.db == MapDatabases.OSCIMAP_READER ||
options.db == MapDatabases.MAP_READER ||
options.db == MapDatabases.TEST_READER)
MapView.enableClosePolygons = true;
else
MapView.enableClosePolygons = false;
clearMap();
tileWorkersProceed();
return true;
}
public Map<String, String> getMapOptions() {
return mMapOptions;
}
public MapPosition getMapFileCenter() {
if (mMapDatabase == null)
return null;
MapInfo mapInfo = mMapDatabase.getMapInfo();
if (mapInfo == null)
return null;
GeoPoint startPos = mapInfo.startPosition;
if (startPos == null)
startPos = mapInfo.mapCenter;
if (startPos == null)
startPos = new GeoPoint(0, 0);
MapPosition mapPosition = new MapPosition();
mapPosition.setPosition(startPos);
if (mapInfo.startZoomLevel == null)
mapPosition.setZoomLevel(12);
else
mapPosition.setZoomLevel((mapInfo.startZoomLevel).byteValue());
return mapPosition;
}
public String getRenderTheme() {
return mRenderTheme;
}
/**
* Sets the internal theme which is used for rendering the map.
*
* @param internalRenderTheme
* the internal rendering theme.
* @return ...
* @throws IllegalArgumentException
* if the supplied internalRenderTheme is null.
*/
public boolean setRenderTheme(InternalRenderTheme internalRenderTheme) {
if (internalRenderTheme == null) {
throw new IllegalArgumentException("render theme must not be null");
}
if (internalRenderTheme.name() == mRenderTheme)
return true;
boolean ret = setRenderTheme((Theme) internalRenderTheme);
if (ret) {
mRenderTheme = internalRenderTheme.name();
}
clearMap();
return ret;
}
/**
* Sets the theme file which is used for rendering the map.
*
* @param renderThemePath
* the path to the XML file which defines the rendering theme.
* @throws IllegalArgumentException
* if the supplied internalRenderTheme is null.
* @throws FileNotFoundException
* if the supplied file does not exist, is a directory or cannot
* be read.
*/
public void setRenderTheme(String renderThemePath) throws FileNotFoundException {
if (renderThemePath == null) {
throw new IllegalArgumentException("render theme path must not be null");
}
boolean ret = setRenderTheme(new ExternalRenderTheme(renderThemePath));
if (ret) {
mRenderTheme = renderThemePath;
}
clearMap();
}
private boolean setRenderTheme(Theme theme) {
tileWorkersPause(true);
InputStream inputStream = null;
try {
inputStream = theme.getRenderThemeAsStream();
IRenderTheme t = RenderThemeHandler.getRenderTheme(inputStream);
t.scaleTextSize(1 + (MapView.dpi / 240 - 1) * 0.5f);
// FIXME !!!
GLRenderer.setRenderTheme(t);
for (TileGenerator g : mTileWorker)
g.setRenderTheme(t);
return true;
} catch (ParserConfigurationException e) {
Log.e(TAG, e.getMessage());
} catch (SAXException e) {
Log.e(TAG, e.getMessage());
} catch (IOException e) {
Log.e(TAG, e.getMessage());
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
tileWorkersProceed();
}
return false;
}
/** /**
* add jobs and remember TileGenerators that stuff needs to be done * add jobs and remember TileGenerators that stuff needs to be done
@ -300,36 +103,36 @@ public class TileLayer extends Layer {
* @param jobs * @param jobs
* tile jobs * tile jobs
*/ */
public void addJobs(MapTile[] jobs) { public void setJobs(MapTile[] jobs) {
if (jobs == null) { if (jobs == null) {
mJobQueue.clear(); mJobQueue.clear();
return; return;
} }
mJobQueue.setJobs(jobs); mJobQueue.setJobs(jobs);
for (int i = 0; i < mNumTileWorker; i++) { for (int i = 0; i < mNumTileLoader; i++) {
TileGenerator m = mTileWorker[i]; T m = mTileLoader.get(i);
synchronized (m) { synchronized (m) {
m.notify(); m.notify();
} }
} }
} }
private void tileWorkersPause(boolean wait) { protected void pauseLoaders(boolean wait) {
for (TileGenerator tileWorker : mTileWorker) { for (T loader : mTileLoader) {
if (!tileWorker.isPausing()) if (!loader.isPausing())
tileWorker.pause(); loader.pause();
} }
if (wait) { if (wait) {
for (TileGenerator tileWorker : mTileWorker) { for (T loader : mTileLoader) {
if (!tileWorker.isPausing()) if (!loader.isPausing())
tileWorker.awaitPausing(); loader.awaitPausing();
} }
} }
} }
private void tileWorkersProceed() { protected void resumeLoaders() {
for (TileGenerator tileWorker : mTileWorker) for (T loader : mTileLoader)
tileWorker.proceed(); loader.proceed();
} }
} }

View File

@ -1,6 +1,5 @@
/* /*
* Copyright 2010, 2011, 2012 mapsforge.org * Copyright 2013 Hannes Janetzek
* Copyright 2013 Hannes Hannes Janetzek
* *
* This program is free software: you can redistribute it and/or modify it under the * 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 * terms of the GNU Lesser General Public License as published by the Free Software
@ -17,32 +16,34 @@ package org.oscim.layers.tile;
import org.oscim.utils.PausableThread; import org.oscim.utils.PausableThread;
/** public abstract class TileLoader extends PausableThread {
* A MapWorker uses a {@link TileGenerator} to generate map tiles. It runs in a private static int id;
* separate thread to avoid blocking the UI thread.
*/ public interface Factory<T extends TileLoader>{
public abstract class MapWorker extends PausableThread { T create(JobQueue jobQueue, TileManager tileManager);
}
private final String THREAD_NAME; private final String THREAD_NAME;
private final JobQueue mJobQueue; private final JobQueue mJobQueue;
private final TileManager mTileManager; private final TileManager mTileManager;
/** public TileLoader(JobQueue jobQueue, TileManager tileManager) {
* @param id
* thread id
* @param jobQueue
* ...
* @param tileManager
* ...
*/
public MapWorker(int id, JobQueue jobQueue, TileManager tileManager) {
super(); super();
mJobQueue = jobQueue; mJobQueue = jobQueue;
mTileManager = tileManager; mTileManager = tileManager;
THREAD_NAME = "TileLoader" + (id++);
THREAD_NAME = "MapWorker" + id;
} }
public abstract void cleanup();
/**
* Load data for 'tile' and file tile.layers for rendering.
* (executed on MapWorker threads)
*/
protected abstract boolean executeJob(MapTile tile);
@Override @Override
protected void doWork() { protected void doWork() {
MapTile tile = mJobQueue.poll(); MapTile tile = mJobQueue.poll();
@ -63,7 +64,6 @@ public abstract class MapWorker extends PausableThread {
} }
} }
protected abstract boolean executeJob(MapTile tile);
@Override @Override
protected String getThreadName() { protected String getThreadName() {

View File

@ -114,9 +114,9 @@ public class TileManager {
}; };
private final float[] mBoxCoords = new float[8]; private final float[] mBoxCoords = new float[8];
private final TileLayer mTileLayer; private final TileLayer<?> mTileLayer;
public TileManager(MapView mapView, TileLayer tileLayer) { public TileManager(MapView mapView, TileLayer<?> tileLayer) {
mMapView = mapView; mMapView = mapView;
mTileLayer = tileLayer; mTileLayer = tileLayer;
@ -197,7 +197,7 @@ public class TileManager {
// start with old jobs while new jobs are calculated, which // start with old jobs while new jobs are calculated, which
// should increase the chance that they are free when new // should increase the chance that they are free when new
// jobs come in. // jobs come in.
mTileLayer.addJobs(null); mTileLayer.setJobs(null);
// load some tiles more than currently visible (* 0.75) // load some tiles more than currently visible (* 0.75)
double scale = pos.scale * 0.9f; double scale = pos.scale * 0.9f;
@ -260,7 +260,7 @@ public class TileManager {
updateTileDistances(jobs, jobs.length, pos); updateTileDistances(jobs, jobs.length, pos);
// sets tiles to state == LOADING // sets tiles to state == LOADING
mTileLayer.addJobs(jobs); mTileLayer.setJobs(jobs);
mJobs.clear(); mJobs.clear();
/* limit cache items */ /* limit cache items */
@ -527,7 +527,7 @@ public class TileManager {
} else if (t.state == STATE_LOADING) { } else if (t.state == STATE_LOADING) {
// NOTE: when set loading to false the tile could be // NOTE: when set loading to false the tile could be
// added to load queue again while still processed in // added to load queue again while still processed in
// TileGenerator => need tile.cancel flag. // MapTileLoader => need tile.cancel flag.
// t.isLoading = false; // t.isLoading = false;
Log.d(TAG, "limitCache: cancel loading " + t + " " + t.distance); Log.d(TAG, "limitCache: cancel loading " + t + " " + t.distance);
} else { } else {
@ -560,7 +560,7 @@ public class TileManager {
} }
/** /**
* called from MapWorker Thread when tile is loaded by TileGenerator * called from MapWorker Thread when tile is loaded by MapTileLoader
* *
* @param tile * @param tile
* Tile ready for upload to GL * Tile ready for upload to GL
@ -570,7 +570,7 @@ public class TileManager {
if (tile.state != STATE_LOADING) { if (tile.state != STATE_LOADING) {
// - should rather be STATE_FAILED // - should rather be STATE_FAILED
// no one should be able to use this tile now, TileGenerator passed // no one should be able to use this tile now, MapTileLoader passed
// it, GL-Thread does nothing until newdata is set. // it, GL-Thread does nothing until newdata is set.
//Log.d(TAG, "passTile: failed loading " + tile); //Log.d(TAG, "passTile: failed loading " + tile);
return true; return true;

View File

@ -24,8 +24,8 @@ import static android.opengl.GLES20.glVertexAttribPointer;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLState;
import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.renderer.GLRenderer.Matrices;
import org.oscim.renderer.GLState;
import org.oscim.theme.renderinstruction.Line; import org.oscim.theme.renderinstruction.Line;
import org.oscim.utils.GlUtils; import org.oscim.utils.GlUtils;
@ -153,8 +153,6 @@ public final class LineRenderer {
glUniform1f(uLineMode, lineMode); glUniform1f(uLineMode, lineMode);
boolean blur = false; boolean blur = false;
// dont increase scale when max is reached
//boolean strokeMaxZoom = zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL;
Layer l = curLayer; Layer l = curLayer;
for (; l != null && l.type == Layer.LINE; l = l.next) { for (; l != null && l.type == Layer.LINE; l = l.next) {

View File

@ -23,8 +23,8 @@ import org.oscim.core.MapPosition;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.database.MapOptions; import org.oscim.database.MapOptions;
import org.oscim.layers.Layer; import org.oscim.layers.Layer;
import org.oscim.layers.tile.TileGenerator; import org.oscim.layers.tile.MapTileLayer;
import org.oscim.layers.tile.TileLayer; import org.oscim.layers.tile.MapTileLoader;
import org.oscim.overlay.BuildingOverlay; import org.oscim.overlay.BuildingOverlay;
import org.oscim.overlay.LabelingOverlay; import org.oscim.overlay.LabelingOverlay;
import org.oscim.overlay.Overlay; import org.oscim.overlay.Overlay;
@ -121,7 +121,7 @@ public class MapView extends RelativeLayout {
mDebugSettings = new DebugSettings(); mDebugSettings = new DebugSettings();
// FIXME // FIXME
TileGenerator.setDebugSettings(mDebugSettings); MapTileLoader.setDebugSettings(mDebugSettings);
mapActivity.registerMapView(this); mapActivity.registerMapView(this);
@ -134,8 +134,8 @@ public class MapView extends RelativeLayout {
redrawMap(false); redrawMap(false);
} }
public TileLayer setBaseMap(MapOptions options) { public MapTileLayer setBaseMap(MapOptions options) {
TileLayer baseLayer = new TileLayer(this); MapTileLayer baseLayer = new MapTileLayer(this);
baseLayer.setMapDatabase(options); baseLayer.setMapDatabase(options);
@ -266,7 +266,7 @@ public class MapView extends RelativeLayout {
*/ */
public void setDebugSettings(DebugSettings debugSettings) { public void setDebugSettings(DebugSettings debugSettings) {
mDebugSettings = debugSettings; mDebugSettings = debugSettings;
TileGenerator.setDebugSettings(debugSettings); MapTileLoader.setDebugSettings(debugSettings);
} }
/** /**
@ -351,4 +351,5 @@ public class MapView extends RelativeLayout {
public boolean getRotationEnabled() { public boolean getRotationEnabled() {
return mRotationEnabled; return mRotationEnabled;
} }
} }