refactoring of TileLayer, some more
This commit is contained in:
parent
2bc71090b3
commit
676b994f2d
@ -15,8 +15,8 @@
|
||||
package org.oscim.core;
|
||||
|
||||
/**
|
||||
* MapElement is created by MapDatabase(s) and passed to TileGenerator
|
||||
* via IMapDatabaseCallback.renderElement() TileGenerator processes the
|
||||
* MapElement is created by MapDatabase(s) and passed to MapTileLoader
|
||||
* via IMapDatabaseCallback.renderElement() MapTileLoader processes the
|
||||
* data into MapTile.layers.
|
||||
* -----
|
||||
* This is really just a buffer object that belongs to MapDatabase, so
|
||||
|
||||
@ -32,7 +32,7 @@ public interface IMapDatabase {
|
||||
* the callback which handles the extracted map elements.
|
||||
* @return true if successful
|
||||
*/
|
||||
public abstract QueryResult executeQuery(MapTile tile,
|
||||
abstract QueryResult executeQuery(MapTile tile,
|
||||
IMapDatabaseCallback mapDatabaseCallback);
|
||||
|
||||
/**
|
||||
@ -40,12 +40,12 @@ public interface IMapDatabase {
|
||||
* @throws IllegalStateException
|
||||
* if no map is currently opened.
|
||||
*/
|
||||
public abstract MapInfo getMapInfo();
|
||||
abstract MapInfo getMapInfo();
|
||||
|
||||
/**
|
||||
* @return true if a map database is currently opened, false otherwise.
|
||||
*/
|
||||
public abstract boolean isOpen();
|
||||
abstract boolean isOpen();
|
||||
|
||||
/**
|
||||
* Opens MapDatabase
|
||||
@ -54,21 +54,21 @@ public interface IMapDatabase {
|
||||
* the options.
|
||||
* @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
|
||||
* map file is currently opened. Should also force to close Socket so that
|
||||
* thread cannot hang in socket.read
|
||||
*/
|
||||
public abstract void close();
|
||||
abstract void close();
|
||||
|
||||
public abstract String getMapProjection();
|
||||
abstract String getMapProjection();
|
||||
|
||||
/**
|
||||
* Cancel loading
|
||||
*/
|
||||
public abstract void cancel();
|
||||
abstract void cancel();
|
||||
|
||||
public static enum QueryResult {
|
||||
SUCCESS,
|
||||
|
||||
@ -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
|
||||
* references to any arrays after callback function returns.
|
||||
|
||||
@ -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();
|
||||
}
|
||||
@ -21,7 +21,7 @@ import org.oscim.utils.quadtree.QuadTree;
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
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.
|
||||
* it belongs to MapWorker/TileGenerator thread.
|
||||
* it belongs to TileLoader thread.
|
||||
*/
|
||||
public final static int STATE_LOADING = 1 << 0;
|
||||
|
||||
@ -66,7 +66,7 @@ public final class MapTile extends Tile {
|
||||
public float distance;
|
||||
|
||||
/**
|
||||
* Tile data set by TileGenerator.
|
||||
* Tile data set by TileLoader.
|
||||
*/
|
||||
public TextItem labels;
|
||||
public Layers layers;
|
||||
|
||||
231
src/org/oscim/layers/tile/MapTileLayer.java
Normal file
231
src/org/oscim/layers/tile/MapTileLayer.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -50,17 +50,17 @@ import android.util.Log;
|
||||
|
||||
/**
|
||||
* @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
|
||||
* 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.
|
||||
* 5. RenderTheme calls IRenderCallback functions with style information
|
||||
* 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 byte LAYERS = 11;
|
||||
@ -83,7 +83,7 @@ public class TileGenerator extends MapWorker implements IRenderCallback, IMapDat
|
||||
private IRenderTheme renderTheme;
|
||||
private int renderLevels;
|
||||
|
||||
// current MapDatabase used by this TileGenerator
|
||||
// current MapDatabase used by this MapTileLoader
|
||||
private IMapDatabase mMapDatabase;
|
||||
|
||||
// currently processed tile
|
||||
@ -117,8 +117,8 @@ public class TileGenerator extends MapWorker implements IRenderCallback, IMapDat
|
||||
|
||||
/**
|
||||
*/
|
||||
public TileGenerator(int id, JobQueue jobQueue, TileManager tileManager) {
|
||||
super(id, jobQueue, tileManager);
|
||||
public MapTileLoader(JobQueue jobQueue, TileManager tileManager) {
|
||||
super(jobQueue, tileManager);
|
||||
|
||||
mClipper = new LineClipper(0, 0, Tile.SIZE, Tile.SIZE, true);
|
||||
|
||||
@ -140,7 +140,7 @@ public class TileGenerator extends MapWorker implements IRenderCallback, IMapDat
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.oscim.layers.tile.ITileGenerator#cleanup()
|
||||
* @see org.oscim.layers.tile.TileLoader#cleanup()
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
@ -148,7 +148,7 @@ public class TileGenerator extends MapWorker implements IRenderCallback, IMapDat
|
||||
}
|
||||
|
||||
/* (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
|
||||
public boolean executeJob(MapTile mapTile) {
|
||||
79
src/org/oscim/layers/tile/TestTileLayer.java
Normal file
79
src/org/oscim/layers/tile/TestTileLayer.java
Normal 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() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,13 +51,11 @@ public class TileDistanceSort {
|
||||
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));
|
||||
if (start == lo)
|
||||
++start;
|
||||
for (; start < hi; ++start)
|
||||
{
|
||||
for (; start < hi; ++start) {
|
||||
MapTile pivot = a[start];
|
||||
|
||||
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);
|
||||
int runHi = lo + 1;
|
||||
if (runHi == hi) {
|
||||
@ -118,8 +115,7 @@ public class TileDistanceSort {
|
||||
return (runHi - lo);
|
||||
}
|
||||
|
||||
private static void reverseRange(MapTile[] a, int lo, int hi)
|
||||
{
|
||||
private static void reverseRange(MapTile[] a, int lo, int hi) {
|
||||
--hi;
|
||||
while (lo < hi) {
|
||||
MapTile t = a[lo];
|
||||
@ -127,4 +123,7 @@ public class TileDistanceSort {
|
||||
a[(hi--)] = t;
|
||||
}
|
||||
}
|
||||
|
||||
private TileDistanceSort() {
|
||||
}
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
}
|
||||
}
|
||||
@ -14,58 +14,43 @@
|
||||
*/
|
||||
package org.oscim.layers.tile;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
|
||||
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.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.xml.sax.SAXException;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class TileLayer extends Layer {
|
||||
private final static String TAG = TileLayer.class.getName();
|
||||
public class TileLayer<T extends TileLoader> extends Layer {
|
||||
//private final static String TAG = TileLayer.class.getName();
|
||||
|
||||
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;
|
||||
private final TileGenerator mTileWorker[];
|
||||
protected final int mNumTileLoader = 4;
|
||||
protected final ArrayList<T> mTileLoader;
|
||||
|
||||
public TileLayer(MapView mapView) {
|
||||
public TileLayer(MapView mapView, TileLoader.Factory<T> factory) {
|
||||
super(mapView);
|
||||
|
||||
// TileManager responsible for adding visible tiles
|
||||
// to load queue and managing in-memory tile cache.
|
||||
mTileManager = new TileManager(mapView, this);
|
||||
|
||||
mJobQueue = new JobQueue();
|
||||
mTileWorker = new TileGenerator[mNumTileWorker];
|
||||
|
||||
TileGenerator.setDebugSettings(mapView.getDebugSettings());
|
||||
|
||||
for (int i = 0; i < mNumTileWorker; i++) {
|
||||
mTileWorker[i] = new TileGenerator(i, mJobQueue, mTileManager);
|
||||
mTileWorker[i].start();
|
||||
// Instantiate TileLoader threads
|
||||
mTileLoader = new ArrayList<T>();
|
||||
for (int i = 0; i < mNumTileLoader; i++) {
|
||||
T tileGenerator = factory.create(mJobQueue, mTileManager);
|
||||
mTileLoader.add(tileGenerator);
|
||||
tileGenerator.start();
|
||||
}
|
||||
|
||||
// RenderLayer is working in GL Thread and actually
|
||||
// drawing loaded tiles to screen.
|
||||
mLayer = new TileRenderLayer(mapView, mTileManager);
|
||||
}
|
||||
|
||||
@ -80,7 +65,6 @@ public class TileLayer extends Layer {
|
||||
mTileManager.init(mMapView.getWidth(), mMapView.getHeight());
|
||||
mClearMap = false;
|
||||
changed = true;
|
||||
Log.d(TAG, "init TileManager ----- ");
|
||||
}
|
||||
if (changed)
|
||||
mTileManager.update(mapPosition);
|
||||
@ -91,7 +75,7 @@ public class TileLayer extends Layer {
|
||||
|
||||
mTileManager.destroy();
|
||||
|
||||
for (TileGenerator tileWorker : mTileWorker) {
|
||||
for (T tileWorker : mTileLoader) {
|
||||
tileWorker.pause();
|
||||
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
|
||||
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
|
||||
@ -300,36 +103,36 @@ public class TileLayer extends Layer {
|
||||
* @param jobs
|
||||
* tile jobs
|
||||
*/
|
||||
public void addJobs(MapTile[] jobs) {
|
||||
public void setJobs(MapTile[] jobs) {
|
||||
if (jobs == null) {
|
||||
mJobQueue.clear();
|
||||
return;
|
||||
}
|
||||
mJobQueue.setJobs(jobs);
|
||||
|
||||
for (int i = 0; i < mNumTileWorker; i++) {
|
||||
TileGenerator m = mTileWorker[i];
|
||||
for (int i = 0; i < mNumTileLoader; i++) {
|
||||
T m = mTileLoader.get(i);
|
||||
synchronized (m) {
|
||||
m.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void tileWorkersPause(boolean wait) {
|
||||
for (TileGenerator tileWorker : mTileWorker) {
|
||||
if (!tileWorker.isPausing())
|
||||
tileWorker.pause();
|
||||
protected void pauseLoaders(boolean wait) {
|
||||
for (T loader : mTileLoader) {
|
||||
if (!loader.isPausing())
|
||||
loader.pause();
|
||||
}
|
||||
if (wait) {
|
||||
for (TileGenerator tileWorker : mTileWorker) {
|
||||
if (!tileWorker.isPausing())
|
||||
tileWorker.awaitPausing();
|
||||
for (T loader : mTileLoader) {
|
||||
if (!loader.isPausing())
|
||||
loader.awaitPausing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void tileWorkersProceed() {
|
||||
for (TileGenerator tileWorker : mTileWorker)
|
||||
tileWorker.proceed();
|
||||
protected void resumeLoaders() {
|
||||
for (T loader : mTileLoader)
|
||||
loader.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||
* Copyright 2013 Hannes Hannes Janetzek
|
||||
* 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
|
||||
@ -17,32 +16,34 @@ package org.oscim.layers.tile;
|
||||
|
||||
import org.oscim.utils.PausableThread;
|
||||
|
||||
/**
|
||||
* A MapWorker uses a {@link TileGenerator} to generate map tiles. It runs in a
|
||||
* separate thread to avoid blocking the UI thread.
|
||||
*/
|
||||
public abstract class MapWorker extends PausableThread {
|
||||
public abstract class TileLoader extends PausableThread {
|
||||
private static int id;
|
||||
|
||||
public interface Factory<T extends TileLoader>{
|
||||
T create(JobQueue jobQueue, TileManager tileManager);
|
||||
}
|
||||
|
||||
private final String THREAD_NAME;
|
||||
private final JobQueue mJobQueue;
|
||||
private final TileManager mTileManager;
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* thread id
|
||||
* @param jobQueue
|
||||
* ...
|
||||
* @param tileManager
|
||||
* ...
|
||||
*/
|
||||
public MapWorker(int id, JobQueue jobQueue, TileManager tileManager) {
|
||||
|
||||
public TileLoader(JobQueue jobQueue, TileManager tileManager) {
|
||||
super();
|
||||
mJobQueue = jobQueue;
|
||||
mTileManager = tileManager;
|
||||
|
||||
THREAD_NAME = "MapWorker" + id;
|
||||
THREAD_NAME = "TileLoader" + (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
|
||||
protected void doWork() {
|
||||
MapTile tile = mJobQueue.poll();
|
||||
@ -63,7 +64,6 @@ public abstract class MapWorker extends PausableThread {
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean executeJob(MapTile tile);
|
||||
|
||||
@Override
|
||||
protected String getThreadName() {
|
||||
@ -114,9 +114,9 @@ public class TileManager {
|
||||
};
|
||||
|
||||
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;
|
||||
mTileLayer = tileLayer;
|
||||
|
||||
@ -197,7 +197,7 @@ public class TileManager {
|
||||
// start with old jobs while new jobs are calculated, which
|
||||
// should increase the chance that they are free when new
|
||||
// jobs come in.
|
||||
mTileLayer.addJobs(null);
|
||||
mTileLayer.setJobs(null);
|
||||
|
||||
// load some tiles more than currently visible (* 0.75)
|
||||
double scale = pos.scale * 0.9f;
|
||||
@ -260,7 +260,7 @@ public class TileManager {
|
||||
updateTileDistances(jobs, jobs.length, pos);
|
||||
|
||||
// sets tiles to state == LOADING
|
||||
mTileLayer.addJobs(jobs);
|
||||
mTileLayer.setJobs(jobs);
|
||||
mJobs.clear();
|
||||
|
||||
/* limit cache items */
|
||||
@ -527,7 +527,7 @@ public class TileManager {
|
||||
} else if (t.state == STATE_LOADING) {
|
||||
// NOTE: when set loading to false the tile could be
|
||||
// added to load queue again while still processed in
|
||||
// TileGenerator => need tile.cancel flag.
|
||||
// MapTileLoader => need tile.cancel flag.
|
||||
// t.isLoading = false;
|
||||
Log.d(TAG, "limitCache: cancel loading " + t + " " + t.distance);
|
||||
} 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
|
||||
* Tile ready for upload to GL
|
||||
@ -570,7 +570,7 @@ public class TileManager {
|
||||
|
||||
if (tile.state != STATE_LOADING) {
|
||||
// - 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.
|
||||
//Log.d(TAG, "passTile: failed loading " + tile);
|
||||
return true;
|
||||
|
||||
@ -24,8 +24,8 @@ import static android.opengl.GLES20.glVertexAttribPointer;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.renderer.GLRenderer;
|
||||
import org.oscim.renderer.GLState;
|
||||
import org.oscim.renderer.GLRenderer.Matrices;
|
||||
import org.oscim.renderer.GLState;
|
||||
import org.oscim.theme.renderinstruction.Line;
|
||||
import org.oscim.utils.GlUtils;
|
||||
|
||||
@ -153,8 +153,6 @@ public final class LineRenderer {
|
||||
glUniform1f(uLineMode, lineMode);
|
||||
|
||||
boolean blur = false;
|
||||
// dont increase scale when max is reached
|
||||
//boolean strokeMaxZoom = zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL;
|
||||
|
||||
Layer l = curLayer;
|
||||
for (; l != null && l.type == Layer.LINE; l = l.next) {
|
||||
|
||||
@ -23,8 +23,8 @@ import org.oscim.core.MapPosition;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.database.MapOptions;
|
||||
import org.oscim.layers.Layer;
|
||||
import org.oscim.layers.tile.TileGenerator;
|
||||
import org.oscim.layers.tile.TileLayer;
|
||||
import org.oscim.layers.tile.MapTileLayer;
|
||||
import org.oscim.layers.tile.MapTileLoader;
|
||||
import org.oscim.overlay.BuildingOverlay;
|
||||
import org.oscim.overlay.LabelingOverlay;
|
||||
import org.oscim.overlay.Overlay;
|
||||
@ -121,7 +121,7 @@ public class MapView extends RelativeLayout {
|
||||
mDebugSettings = new DebugSettings();
|
||||
|
||||
// FIXME
|
||||
TileGenerator.setDebugSettings(mDebugSettings);
|
||||
MapTileLoader.setDebugSettings(mDebugSettings);
|
||||
|
||||
mapActivity.registerMapView(this);
|
||||
|
||||
@ -134,8 +134,8 @@ public class MapView extends RelativeLayout {
|
||||
redrawMap(false);
|
||||
}
|
||||
|
||||
public TileLayer setBaseMap(MapOptions options) {
|
||||
TileLayer baseLayer = new TileLayer(this);
|
||||
public MapTileLayer setBaseMap(MapOptions options) {
|
||||
MapTileLayer baseLayer = new MapTileLayer(this);
|
||||
|
||||
baseLayer.setMapDatabase(options);
|
||||
|
||||
@ -266,7 +266,7 @@ public class MapView extends RelativeLayout {
|
||||
*/
|
||||
public void setDebugSettings(DebugSettings debugSettings) {
|
||||
mDebugSettings = debugSettings;
|
||||
TileGenerator.setDebugSettings(debugSettings);
|
||||
MapTileLoader.setDebugSettings(debugSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -351,4 +351,5 @@ public class MapView extends RelativeLayout {
|
||||
public boolean getRotationEnabled() {
|
||||
return mRotationEnabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user