keep mapfile-writer/db from bit-rotting

This commit is contained in:
Hannes Janetzek 2012-09-19 00:42:49 +02:00
parent 19344e39cf
commit 4a5142fdf6
8 changed files with 203 additions and 103 deletions

View File

@ -32,12 +32,15 @@ import org.oscim.database.mapfile.header.MapFileInfo;
import org.oscim.database.mapfile.header.SubFileParameter; import org.oscim.database.mapfile.header.SubFileParameter;
import org.oscim.view.generator.JobTile; import org.oscim.view.generator.JobTile;
import android.os.Environment;
/** /**
* A class for reading binary map files. * A class for reading binary map files.
* <p> * <p>
* This class is not thread-safe. Each thread should use its own instance. * This class is not thread-safe. Each thread should use its own instance.
* *
* @see <a href="http://code.google.com/p/mapsforge/wiki/SpecificationBinaryMapFile">Specification</a> * @see <a
* href="http://code.google.com/p/mapsforge/wiki/SpecificationBinaryMapFile">Specification</a>
*/ */
public class MapDatabase implements IMapDatabase { public class MapDatabase implements IMapDatabase {
/** /**
@ -83,7 +86,8 @@ public class MapDatabase implements IMapDatabase {
private static final int MAXIMUM_WAY_NODES_SEQUENCE_LENGTH = 8192; private static final int MAXIMUM_WAY_NODES_SEQUENCE_LENGTH = 8192;
/** /**
* Maximum number of map objects in the zoom table which is considered as valid. * Maximum number of map objects in the zoom table which is considered as
* valid.
*/ */
private static final int MAXIMUM_ZOOM_TABLE_OBJECTS = 65536; private static final int MAXIMUM_ZOOM_TABLE_OBJECTS = 65536;
@ -270,17 +274,28 @@ public class MapDatabase implements IMapDatabase {
*/ */
@Override @Override
public OpenResult open(Map<String, String> options) { public OpenResult open(Map<String, String> options) {
// if (options == null) {
// options = new HashMap<String, String>(1);
// options.put("mapfile", "/sdcard/bremen.map");
// }
try { try {
if (options == null || options.get("mapfile") == null) { // if (options == null || options.get("mapfile") == null) {
// throw new IllegalArgumentException("mapFile must not be null"); // // throw new
return new OpenResult("no file!"); // // IllegalArgumentException("mapFile must not be null");
} // return new OpenResult("no file!");
// }
// make sure to close any previously opened file first // make sure to close any previously opened file first
close(); close();
File file = new File(options.get("mapfile")); File file = new File(Environment.getExternalStorageDirectory().getPath()
+ "/bremen.map");
System.out.println("load " + file + " "
+ (Environment.getExternalStorageDirectory().getPath()
+ "/bremen.map"));
// File file = new File(options.get("mapfile"));
// check if the file exists and is readable // check if the file exists and is readable
if (!file.exists()) { if (!file.exists()) {
@ -370,7 +385,8 @@ public class MapDatabase implements IMapDatabase {
} }
/** /**
* Processes a single block and executes the callback functions on all map elements. * Processes a single block and executes the callback functions on all map
* elements.
* *
* @param queryParameters * @param queryParameters
* the parameters of the current query. * the parameters of the current query.
@ -445,7 +461,8 @@ public class MapDatabase implements IMapDatabase {
for (long row = queryParameters.fromBlockY; row <= queryParameters.toBlockY; ++row) { for (long row = queryParameters.fromBlockY; row <= queryParameters.toBlockY; ++row) {
for (long column = queryParameters.fromBlockX; column <= queryParameters.toBlockX; ++column) { for (long column = queryParameters.fromBlockX; column <= queryParameters.toBlockX; ++column) {
// calculate the actual block number of the needed block in the file // calculate the actual block number of the needed block in the
// file
long blockNumber = row * subFileParameter.blocksWidth + column; long blockNumber = row * subFileParameter.blocksWidth + column;
// get the current index entry // get the current index entry
@ -454,7 +471,8 @@ public class MapDatabase implements IMapDatabase {
// check if the current query would still return a water tile // check if the current query would still return a water tile
if (queryIsWater) { if (queryIsWater) {
// check the water flag of the current block in its index entry // check the water flag of the current block in its index
// entry
queryIsWater &= (currentBlockIndexEntry & BITMASK_INDEX_WATER) != 0; queryIsWater &= (currentBlockIndexEntry & BITMASK_INDEX_WATER) != 0;
// queryReadWaterInfo = true; // queryReadWaterInfo = true;
} }
@ -496,7 +514,8 @@ public class MapDatabase implements IMapDatabase {
// the current block is empty, continue with the next block // the current block is empty, continue with the next block
continue; continue;
} else if (currentBlockSize > ReadBuffer.MAXIMUM_BUFFER_SIZE) { } else if (currentBlockSize > ReadBuffer.MAXIMUM_BUFFER_SIZE) {
// the current block is too large, continue with the next block // the current block is too large, continue with the next
// block
LOG.warning("current block size too large: " + currentBlockSize); LOG.warning("current block size too large: " + currentBlockSize);
continue; continue;
} else if (currentBlockPointer + currentBlockSize > mFileSize) { } else if (currentBlockPointer + currentBlockSize > mFileSize) {
@ -538,7 +557,8 @@ public class MapDatabase implements IMapDatabase {
// Tag[] tags = new Tag[1]; // Tag[] tags = new Tag[1];
// tags[0] = TAG_NATURAL_WATER; // tags[0] = TAG_NATURAL_WATER;
// //
// System.arraycopy(WATER_TILE_COORDINATES, 0, mWayNodes, mWayNodePosition, 8); // System.arraycopy(WATER_TILE_COORDINATES, 0, mWayNodes,
// mWayNodePosition, 8);
// mWayNodePosition += 8; // mWayNodePosition += 8;
// mapDatabaseCallback.renderWaterBackground(tags, wayDataContainer); // mapDatabaseCallback.renderWaterBackground(tags, wayDataContainer);
// } // }
@ -548,7 +568,8 @@ public class MapDatabase implements IMapDatabase {
/** /**
* Processes the block signature, if present. * Processes the block signature, if present.
* *
* @return true if the block signature could be processed successfully, false otherwise. * @return true if the block signature could be processed successfully,
* false otherwise.
*/ */
private boolean processBlockSignature() { private boolean processBlockSignature() {
if (mDebugFile) { if (mDebugFile) {
@ -569,7 +590,8 @@ public class MapDatabase implements IMapDatabase {
* the callback which handles the extracted POIs. * the callback which handles the extracted POIs.
* @param numberOfPois * @param numberOfPois
* how many POIs should be processed. * how many POIs should be processed.
* @return true if the POIs could be processed successfully, false otherwise. * @return true if the POIs could be processed successfully, false
* otherwise.
*/ */
private boolean processPOIs(IMapDatabaseCallback mapDatabaseCallback, int numberOfPois) { private boolean processPOIs(IMapDatabaseCallback mapDatabaseCallback, int numberOfPois) {
Tag[] poiTags = sMapFileHeader.getMapFileInfo().poiTags; Tag[] poiTags = sMapFileHeader.getMapFileInfo().poiTags;
@ -637,7 +659,8 @@ public class MapDatabase implements IMapDatabase {
// check if the POI has an elevation // check if the POI has an elevation
if ((featureByte & POI_FEATURE_ELEVATION) != 0) { if ((featureByte & POI_FEATURE_ELEVATION) != 0) {
mReadBuffer.readSignedInt(); mReadBuffer.readSignedInt();
// mReadBuffer.getPositionAndSkip();// tags.add(new Tag(Tag.TAG_KEY_ELE, // mReadBuffer.getPositionAndSkip();// tags.add(new
// Tag(Tag.TAG_KEY_ELE,
// Integer.toString(mReadBuffer.readSignedInt()))); // Integer.toString(mReadBuffer.readSignedInt())));
} }
@ -785,7 +808,8 @@ public class MapDatabase implements IMapDatabase {
* the callback which handles the extracted ways. * the callback which handles the extracted ways.
* @param numberOfWays * @param numberOfWays
* how many ways should be processed. * how many ways should be processed.
* @return true if the ways could be processed successfully, false otherwise. * @return true if the ways could be processed successfully, false
* otherwise.
*/ */
private boolean processWays(QueryParameters queryParameters, private boolean processWays(QueryParameters queryParameters,
IMapDatabaseCallback mapDatabaseCallback, IMapDatabaseCallback mapDatabaseCallback,
@ -882,12 +906,13 @@ public class MapDatabase implements IMapDatabase {
textPos[0] = mReadBuffer.readUnsignedInt(); textPos[0] = mReadBuffer.readUnsignedInt();
String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset
+ textPos[0]); + textPos[0]);
if (changed) { // if (changed) {
Tag[] tmp = tags; // Tag[] tmp = tags;
tags = new Tag[tmp.length + 1]; // tags = new Tag[tmp.length + 1];
System.arraycopy(tmp, 0, tags, 0, tmp.length); // System.arraycopy(tmp, 0, tags, 0, tmp.length);
} // }
tags[tags.length - 1] = new Tag("name", str, false); // tags[tags.length - 1] = new Tag(Tag.TAG_KEY_NAME, str,
// false);
} }
else else
textPos[0] = -1; textPos[0] = -1;
@ -930,8 +955,13 @@ public class MapDatabase implements IMapDatabase {
return false; return false;
// wayDataContainer.textPos = textPos; // wayDataContainer.textPos = textPos;
int l = wayLengths[0];
boolean closed = mWayNodes[0] == mWayNodes[l - 2]
&& mWayNodes[1] == mWayNodes[l - 1];
mapDatabaseCallback mapDatabaseCallback
.renderWay(layer, tags, mWayNodes, wayLengths, changed); .renderWay(layer, tags, mWayNodes, wayLengths, closed);
} }
} }
@ -950,7 +980,8 @@ public class MapDatabase implements IMapDatabase {
return labelPosition; return labelPosition;
} }
// private int readOptionalWayDataBlocksByte(boolean featureWayDataBlocksByte) { // private int readOptionalWayDataBlocksByte(boolean
// featureWayDataBlocksByte) {
// if (featureWayDataBlocksByte) { // if (featureWayDataBlocksByte) {
// // get and check the number of way data blocks (VBE-U) // // get and check the number of way data blocks (VBE-U)
// return mReadBuffer.readUnsignedInt(); // return mReadBuffer.readUnsignedInt();

View File

@ -85,7 +85,8 @@ public class MapFileHeader {
* the ReadBuffer for the file data. * the ReadBuffer for the file data.
* @param fileSize * @param fileSize
* the size of the map file in bytes. * the size of the map file in bytes.
* @return a FileOpenResult containing an error message in case of a failure. * @return a FileOpenResult containing an error message in case of a
* failure.
* @throws IOException * @throws IOException
* if an error occurs while reading the file. * if an error occurs while reading the file.
*/ */
@ -107,7 +108,8 @@ public class MapFileHeader {
return openResult; return openResult;
} }
openResult = RequiredFields.readFileSize(readBuffer, fileSize, mapFileInfoBuilder); openResult = RequiredFields
.readFileSize(readBuffer, fileSize, mapFileInfoBuilder);
if (!openResult.isSuccess()) { if (!openResult.isSuccess()) {
return openResult; return openResult;
} }
@ -151,8 +153,24 @@ public class MapFileHeader {
if (!openResult.isSuccess()) { if (!openResult.isSuccess()) {
return openResult; return openResult;
} }
int[] level = new int[20];
level[17] = 16;
level[16] = 16;
level[15] = 16;
level[14] = 13;
level[13] = 13;
level[12] = 13;
level[11] = 10;
level[10] = 10;
level[9] = 10;
level[8] = 7;
level[7] = 7;
level[6] = 7;
mapFileInfoBuilder.zoomLevel = level;
this.mapFileInfo = mapFileInfoBuilder.build(); this.mapFileInfo = mapFileInfoBuilder.build();
return OpenResult.SUCCESS; return OpenResult.SUCCESS;
} }
@ -196,7 +214,8 @@ public class MapFileHeader {
// check for valid zoom level range // check for valid zoom level range
if (zoomLevelMin > zoomLevelMax) { if (zoomLevelMin > zoomLevelMax) {
return new OpenResult("invalid zoom level range: " + zoomLevelMin + SPACE + zoomLevelMax); return new OpenResult("invalid zoom level range: " + zoomLevelMin + SPACE
+ zoomLevelMax);
} }
// get and check the start address of the sub-file (8 bytes) // get and check the start address of the sub-file (8 bytes)

View File

@ -59,7 +59,8 @@ public class MapFileInfo extends org.oscim.database.MapInfo {
mapFileInfoBuilder.fileVersion, mapFileInfoBuilder.fileVersion,
mapFileInfoBuilder.optionalFields.languagePreference, mapFileInfoBuilder.optionalFields.languagePreference,
mapFileInfoBuilder.optionalFields.comment, mapFileInfoBuilder.optionalFields.comment,
mapFileInfoBuilder.optionalFields.createdBy, null); mapFileInfoBuilder.optionalFields.createdBy,
mapFileInfoBuilder.zoomLevel);
debugFile = mapFileInfoBuilder.optionalFields.isDebugFile; debugFile = mapFileInfoBuilder.optionalFields.isDebugFile;

View File

@ -28,6 +28,7 @@ class MapFileInfoBuilder {
String projectionName; String projectionName;
int tilePixelSize; int tilePixelSize;
Tag[] wayTags; Tag[] wayTags;
int[] zoomLevel;
MapFileInfo build() { MapFileInfo build() {
return new MapFileInfo(this); return new MapFileInfo(this);

View File

@ -49,24 +49,17 @@ import android.view.MotionEvent;
import android.widget.FrameLayout; import android.widget.FrameLayout;
/** /**
* A MapView shows a map on the display of the device. It handles all user input and touch gestures to move and zoom the * A MapView shows a map on the display of the device. It handles all user input
* map. * and touch gestures to move and zoom the map.
*/ */
public class MapView extends FrameLayout { public class MapView extends FrameLayout {
final static String TAG = "MapView"; final static String TAG = "MapView";
/**
* Default render theme of the MapView.
*/
public static final InternalRenderTheme DEFAULT_RENDER_THEME = InternalRenderTheme.OSMARENDER;
// private static final float DEFAULT_TEXT_SCALE = 1;
// private static final Byte DEFAULT_START_ZOOM_LEVEL = Byte.valueOf((byte) 16);
public final static boolean debugFrameTime = false; public final static boolean debugFrameTime = false;
public final static boolean testRegionZoom = false; public final static boolean testRegionZoom = false;
private final boolean mDebugDatabase = false;
RegionLookup mRegionLookup; RegionLookup mRegionLookup;
public boolean enableRotation = false; public boolean enableRotation = false;
@ -94,7 +87,8 @@ public class MapView extends FrameLayout {
* @param context * @param context
* the enclosing MapActivity instance. * the enclosing MapActivity instance.
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the context object is not an instance of {@link MapActivity} . * if the context object is not an instance of
* {@link MapActivity} .
*/ */
public MapView(Context context) { public MapView(Context context) {
this(context, null, MapDatabases.MAP_READER); this(context, null, MapDatabases.MAP_READER);
@ -106,14 +100,13 @@ public class MapView extends FrameLayout {
* @param attributeSet * @param attributeSet
* a set of attributes. * a set of attributes.
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the context object is not an instance of {@link MapActivity} . * if the context object is not an instance of
* {@link MapActivity} .
*/ */
public MapView(Context context, AttributeSet attributeSet) { public MapView(Context context, AttributeSet attributeSet) {
this(context, attributeSet, MapDatabaseFactory.getMapDatabase(attributeSet)); this(context, attributeSet, MapDatabaseFactory.getMapDatabase(attributeSet));
} }
private boolean mDebugDatabase = false;
private MapView(Context context, AttributeSet attributeSet, private MapView(Context context, AttributeSet attributeSet,
MapDatabases mapDatabaseType) { MapDatabases mapDatabaseType) {
@ -150,8 +143,11 @@ public class MapView extends FrameLayout {
for (int i = 0; i < mNumMapWorkers; i++) { for (int i = 0; i < mNumMapWorkers; i++) {
IMapDatabase mapDatabase; IMapDatabase mapDatabase;
if (mDebugDatabase) { if (mDebugDatabase) {
// mapDatabase = MapDatabaseFactory
// .createMapDatabase(MapDatabases.TEST_READER);
mapDatabase = MapDatabaseFactory mapDatabase = MapDatabaseFactory
.createMapDatabase(MapDatabases.TEST_READER); .createMapDatabase(MapDatabases.MAP_READER);
mNumMapWorkers = 1;
} else { } else {
mapDatabase = MapDatabaseFactory.createMapDatabase(mapDatabaseType); mapDatabase = MapDatabaseFactory.createMapDatabase(mapDatabaseType);
} }
@ -392,7 +388,8 @@ public class MapView extends FrameLayout {
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the supplied internalRenderTheme is null. * if the supplied internalRenderTheme is null.
* @throws FileNotFoundException * @throws FileNotFoundException
* if the supplied file does not exist, is a directory or cannot be read. * if the supplied file does not exist, is a directory or cannot
* be read.
*/ */
public void setRenderTheme(String renderThemePath) throws FileNotFoundException { public void setRenderTheme(String renderThemePath) throws FileNotFoundException {
if (renderThemePath == null) { if (renderThemePath == null) {
@ -505,7 +502,8 @@ public class MapView extends FrameLayout {
} }
/** /**
* @return true if the current center position of this MapView is valid, false otherwise. * @return true if the current center position of this MapView is valid,
* false otherwise.
*/ */
boolean hasValidCenter() { boolean hasValidCenter() {
MapInfo mapInfo; MapInfo mapInfo;
@ -639,7 +637,8 @@ public class MapView extends FrameLayout {
// } // }
// /** // /**
// * Sets the text scale for the map rendering. Has no effect in downloading mode. // * Sets the text scale for the map rendering. Has no effect in downloading
// mode.
// * // *
// * @param textScale // * @param textScale
// * the new text scale for the map rendering. // * the new text scale for the map rendering.

View File

@ -102,7 +102,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// lock to synchronize Main- and GL-Thread // lock to synchronize Main- and GL-Thread
static ReentrantLock tilelock = new ReentrantLock(); static ReentrantLock tilelock = new ReentrantLock();
// used for passing tiles to be rendered from TileLoader(Main-Thread) to GLThread // used for passing tiles to be rendered from TileLoader(Main-Thread) to
// GLThread
static class TilesData { static class TilesData {
int cnt = 0; int cnt = 0;
final MapTile[] tiles; final MapTile[] tiles;
@ -337,7 +338,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
ShortBuffer sbuf = null; ShortBuffer sbuf = null;
// use multiple buffers to avoid overwriting buffer while current // use multiple buffers to avoid overwriting buffer while current
// data is uploaded (or rather the blocking which is probably done to avoid this) // data is uploaded (or rather the blocking which is probably done to
// avoid this)
if (uploadCnt >= rotateBuffers) { if (uploadCnt >= rotateBuffers) {
uploadCnt = 0; uploadCnt = 0;
GLES20.glFlush(); GLES20.glFlush();
@ -453,7 +455,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// on HTC it causes oom exception?! // on HTC it causes oom exception?!
// glBindBuffer(GL_ARRAY_BUFFER, vbo.id); // glBindBuffer(GL_ARRAY_BUFFER, vbo.id);
// glBufferData(GL_ARRAY_BUFFER, 0, null, GLES20.GL_STATIC_DRAW); // glBufferData(GL_ARRAY_BUFFER, 0, null,
// GLES20.GL_STATIC_DRAW);
// recreate vbo instead // recreate vbo instead
buf[0] = vbo.id; buf[0] = vbo.id;
@ -581,7 +584,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
} }
} }
// proxies are clipped to the region where nothing was drawn to depth buffer // proxies are clipped to the region where nothing was drawn to depth
// buffer
// TODO draw all parent before grandparent // TODO draw all parent before grandparent
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible && !tiles[i].isReady) { if (tiles[i].isVisible && !tiles[i].isReady) {
@ -819,12 +823,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mMapView.redrawMap(); mMapView.redrawMap();
} }
void clearTiles() { void clearTiles(int numTiles) {
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
* (mHeight / (Tile.TILE_SIZE / 2) + 2);
Log.d(TAG, "clearTiles " + numTiles);
drawTiles = new TilesData(numTiles); drawTiles = new TilesData(numTiles);
curTiles = new TilesData(numTiles); curTiles = new TilesData(numTiles);
} }

View File

@ -20,6 +20,7 @@ import java.util.Collections;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.core.MercatorProjection; import org.oscim.core.MercatorProjection;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.database.MapInfo;
import org.oscim.theme.RenderTheme; import org.oscim.theme.RenderTheme;
import org.oscim.utils.GlConfigChooser; import org.oscim.utils.GlConfigChooser;
import org.oscim.view.MapView; import org.oscim.view.MapView;
@ -58,7 +59,11 @@ public class MapRenderer extends GLSurfaceView {
// private static MapPosition mCurPosition, mDrawPosition; // private static MapPosition mCurPosition, mDrawPosition;
private static int mWidth = 0, mHeight = 0; private static int mWidth = 0, mHeight = 0;
private static TilesData newTiles; private static TilesData mCurrentTiles;
// map zoom-level to available zoom-levels in MapDatabase
// e.g. 16->16, 15->16, 14->13, 13->13, 12->13,....
private static int[] mZoomLevels;
public MapRenderer(Context context, MapView mapView) { public MapRenderer(Context context, MapView mapView) {
super(context); super(context);
@ -90,8 +95,9 @@ public class MapRenderer extends GLSurfaceView {
* called by MapView when position or map settings changes * called by MapView when position or map settings changes
*/ */
/** /**
* Update list of visible tiles and passes them to MapRenderer, when not available tiles are created and added to * Update list of visible tiles and passes them to MapRenderer, when not
* JobQueue (mapView.addJobs) for loading by TileGenerator class * available tiles are created and added to JobQueue (mapView.addJobs) for
* loading by MapGenerator class
* *
* @param clear * @param clear
* ... * ...
@ -108,33 +114,35 @@ public class MapRenderer extends GLSurfaceView {
MapPosition mapPosition = mMapView.getMapPosition().getMapPosition(); MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
if (mapPosition == null) { if (mapPosition == null) {
Log.d(TAG, ">>> no map position"); Log.d(TAG, "X no map position");
return; return;
} }
if (clear) { if (clear) {
// remove all tiles references
Log.d(TAG, "CLEAR"); Log.d(TAG, "CLEAR");
synchronized (GLRenderer.lock) {
for (MapTile t : mTiles)
clearTile(t);
mTiles.clear();
mTilesLoaded.clear();
QuadTree.init();
}
mInitial = true; mInitial = true;
// FIXME still needed?
GLRenderer.tilelock.lock();
for (MapTile t : mTiles)
clearTile(t);
mTiles.clear();
mTilesLoaded.clear();
QuadTree.init();
GLRenderer.tilelock.unlock();
} }
if (mInitial) { if (mInitial) {
mRenderer.clearTiles(); // set up TileData arrays that are passed to gl-thread
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2) int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
* (mHeight / (Tile.TILE_SIZE / 2) + 2); * (mHeight / (Tile.TILE_SIZE / 2) + 2);
Log.d(TAG, "newTiles: " + numTiles);
newTiles = new TilesData(numTiles); mRenderer.clearTiles(numTiles);
mCurrentTiles = new TilesData(numTiles);
MapInfo mapInfo = mMapView.getMapDatabase().getMapInfo();
if (mapInfo != null)
mZoomLevels = mapInfo.zoomLevel;
} }
byte zoomLevel = mapPosition.zoomLevel; byte zoomLevel = mapPosition.zoomLevel;
@ -197,7 +205,16 @@ public class MapRenderer extends GLSurfaceView {
} }
private static boolean updateVisibleList(MapPosition mapPosition, int zdir) { /**
* set mCurrentTiles for the visible tiles and pass it to GLRenderer, add
* jobs for not yet loaded tiles
*
* @param mapPosition
* the current MapPosition
* @param zdir
* zoom direction
*/
private static void updateVisibleList(MapPosition mapPosition, int zdir) {
double x = mapPosition.x; double x = mapPosition.x;
double y = mapPosition.y; double y = mapPosition.y;
byte zoomLevel = mapPosition.zoomLevel; byte zoomLevel = mapPosition.zoomLevel;
@ -223,12 +240,28 @@ public class MapRenderer extends GLSurfaceView {
mMapView.addJobs(null); mMapView.addJobs(null);
int tiles = 0; int tiles = 0;
if (newTiles == null) int max = mCurrentTiles.tiles.length - 1;
return false;
int max = newTiles.tiles.length - 1; boolean fetchChildren = false;
boolean fetchParent = false;
boolean fetchProxy = false;
if (mZoomLevels != null) {
// check MapDatabase zoom-level-mapping
if (mZoomLevels[zoomLevel] == 0) {
mCurrentTiles.cnt = 0;
mCurrentTiles = GLRenderer.updateTiles(mapPosition, mCurrentTiles);
return;
}
boolean prefetchChildren = true; if (mZoomLevels[zoomLevel] > zoomLevel) {
fetchChildren = true;
fetchProxy = true;
}
else if (mZoomLevels[zoomLevel] < zoomLevel) {
fetchParent = true;
fetchProxy = true;
}
}
for (int yy = tileTop; yy <= tileBottom; yy++) { for (int yy = tileTop; yy <= tileBottom; yy++) {
for (int xx = tileLeft; xx <= tileRight; xx++) { for (int xx = tileLeft; xx <= tileRight; xx++) {
@ -245,17 +278,34 @@ public class MapRenderer extends GLSurfaceView {
mTiles.add(tile); mTiles.add(tile);
} }
newTiles.tiles[tiles++] = tile; mCurrentTiles.tiles[tiles++] = tile;
if (prefetchChildren) { if (!fetchProxy && !(tile.isLoading || tile.newData || tile.isReady)) {
}
if (!(tile.isLoading || tile.newData || tile.isReady)) {
mJobList.add(tile); mJobList.add(tile);
} }
if (zdir > 0 && zoomLevel > 0) { if (fetchChildren) {
byte z = (byte) (zoomLevel + 1);
for (int i = 0; i < 4; i++) {
int cx = (xx << 1) + (i % 2);
int cy = (yy << 1) + (i >> 1);
MapTile c = QuadTree.getTile(cx, cy, z);
if (c == null) {
c = new MapTile(cx, cy, z);
QuadTree.add(c);
mTiles.add(c);
}
if (!(c.isLoading || c.newData || c.isReady)) {
mJobList.add(c);
}
}
}
if (fetchParent || (!fetchProxy && zdir > 0 && zoomLevel > 0)) {
// prefetch parent // prefetch parent
MapTile parent = tile.rel.parent.tile; MapTile parent = tile.rel.parent.tile;
@ -275,8 +325,8 @@ public class MapRenderer extends GLSurfaceView {
} }
// pass new tile list to glThread // pass new tile list to glThread
newTiles.cnt = tiles; mCurrentTiles.cnt = tiles;
newTiles = GLRenderer.updateTiles(mapPosition, newTiles); mCurrentTiles = GLRenderer.updateTiles(mapPosition, mCurrentTiles);
// note: this sets isLoading == true for all job tiles // note: this sets isLoading == true for all job tiles
if (mJobList.size() > 0) { if (mJobList.size() > 0) {
@ -284,8 +334,6 @@ public class MapRenderer extends GLSurfaceView {
Collections.sort(mJobList); Collections.sort(mJobList);
mMapView.addJobs(mJobList); mMapView.addJobs(mJobList);
} }
return true;
} }
private static void clearTile(MapTile t) { private static void clearTile(MapTile t) {
@ -311,10 +359,6 @@ public class MapRenderer extends GLSurfaceView {
QuadTree.remove(t); QuadTree.remove(t);
} }
// private static boolean tileInUse(MapTile t) {
// return (t.isActive || t.refs != 0);
// }
private static void updateTileDistances(ArrayList<?> tiles, private static void updateTileDistances(ArrayList<?> tiles,
MapPosition mapPosition) { MapPosition mapPosition) {
int h = (Tile.TILE_SIZE >> 1); int h = (Tile.TILE_SIZE >> 1);
@ -335,7 +379,8 @@ public class MapRenderer extends GLSurfaceView {
if (diff == 0) { if (diff == 0) {
dx = (t.pixelX + h) - x; dx = (t.pixelX + h) - x;
dy = (t.pixelY + h) - y; dy = (t.pixelY + h) - y;
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) * 0.25f; // t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) *
// 0.25f;
t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * 0.25f; t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * 0.25f;
} else if (diff > 0) { } else if (diff > 0) {
// tile zoom level is child of current // tile zoom level is child of current
@ -356,7 +401,8 @@ public class MapRenderer extends GLSurfaceView {
dx = ((t.pixelX + h) << -diff) - x; dx = ((t.pixelX + h) << -diff) - x;
dy = ((t.pixelY + h) << -diff) - y; dy = ((t.pixelY + h) << -diff) - y;
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) * (-diff * 0.5f); // t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) *
// (-diff * 0.5f);
t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * (-diff * 0.5f); t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * (-diff * 0.5f);
} }
} }
@ -455,7 +501,8 @@ public class MapRenderer extends GLSurfaceView {
} }
if (t.isLocked()) { if (t.isLocked()) {
// Log.d(TAG, "keep unused tile data: " + t + " " + t.isActive); // Log.d(TAG, "keep unused tile data: " + t + " " +
// t.isActive);
i++; i++;
continue; continue;
} }
@ -480,7 +527,8 @@ public class MapRenderer extends GLSurfaceView {
MapTile tile = (MapTile) jobTile; MapTile tile = (MapTile) jobTile;
if (!tile.isLoading) { if (!tile.isLoading) {
// no one should be able to use this tile now, mapgenerator passed it, // no one should be able to use this tile now, mapgenerator passed
// it,
// glthread does nothing until newdata is set. // glthread does nothing until newdata is set.
Log.d(TAG, "passTile: canceled " + tile); Log.d(TAG, "passTile: canceled " + tile);
synchronized (mTilesLoaded) { synchronized (mTilesLoaded) {

View File

@ -246,7 +246,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
@Override @Override
public void renderPointOfInterestCaption(Caption caption) { public void renderPointOfInterestCaption(Caption caption) {
// Log.d(TAG, "renderPointOfInterestCaption: " + mPoiX + " " + mPoiY + " " // Log.d(TAG, "renderPointOfInterestCaption: " + mPoiX + " " + mPoiY +
// " "
// + mTagName); // + mTagName);
if (mTagName == null) if (mTagName == null)
@ -266,7 +267,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
if (mTagName == null) if (mTagName == null)
return; return;
if (pathText.textKey == mTagEmptyName.key) { if (pathText.textKey == mTagEmptyName.key && mTagName.value != null) {
mLabels = WayDecorator.renderText(mCoords, mTagName.value, pathText, 0, mLabels = WayDecorator.renderText(mCoords, mTagName.value, pathText, 0,
mIndices[0], mLabels); mIndices[0], mLabels);
@ -509,7 +510,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
* Sets the scale stroke factor for the given zoom level. * Sets the scale stroke factor for the given zoom level.
* *
* @param zoomLevel * @param zoomLevel
* the zoom level for which the scale stroke factor should be set. * the zoom level for which the scale stroke factor should be
* set.
*/ */
private void setScaleStrokeWidth(byte zoomLevel) { private void setScaleStrokeWidth(byte zoomLevel) {
int zoomLevelDiff = Math.max(zoomLevel - STROKE_MIN_ZOOM_LEVEL, 0); int zoomLevelDiff = Math.max(zoomLevel - STROKE_MIN_ZOOM_LEVEL, 0);