keep mapfile-writer/db from bit-rotting
This commit is contained in:
parent
19344e39cf
commit
4a5142fdf6
@ -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();
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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) {
|
||||||
mInitial = true;
|
|
||||||
// FIXME still needed?
|
|
||||||
GLRenderer.tilelock.lock();
|
|
||||||
|
|
||||||
for (MapTile t : mTiles)
|
for (MapTile t : mTiles)
|
||||||
clearTile(t);
|
clearTile(t);
|
||||||
|
|
||||||
mTiles.clear();
|
mTiles.clear();
|
||||||
mTilesLoaded.clear();
|
mTilesLoaded.clear();
|
||||||
QuadTree.init();
|
QuadTree.init();
|
||||||
GLRenderer.tilelock.unlock();
|
}
|
||||||
|
mInitial = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user