switch to ShortBuffer for half-float, shader tweaks,..

This commit is contained in:
Hannes Janetzek 2012-06-20 17:24:38 +02:00
parent 5da8c6ed0d
commit f977fec1ae
12 changed files with 376 additions and 227 deletions

View File

@ -125,7 +125,8 @@ public class MapView extends GLSurfaceView {
super(context, attributeSet);
if (!(context instanceof MapActivity)) {
throw new IllegalArgumentException("context is not an instance of MapActivity");
throw new IllegalArgumentException(
"context is not an instance of MapActivity");
}
setWillNotDraw(true);
setWillNotCacheDrawing(true);
@ -138,7 +139,8 @@ public class MapView extends GLSurfaceView {
mMapController = new MapController(this);
// mMapDatabase = MapDatabaseFactory.createMapDatabase(MapDatabaseInternal.POSTGIS_READER);
mMapDatabase = MapDatabaseFactory.createMapDatabase(MapDatabaseInternal.MAP_READER);
mMapDatabase = MapDatabaseFactory
.createMapDatabase(MapDatabaseInternal.MAP_READER);
mMapViewPosition = new MapViewPosition(this);
mMapScaleBar = new MapScaleBar(this);
@ -327,7 +329,8 @@ public class MapView extends GLSurfaceView {
* the new center point of the map.
*/
public void setCenter(GeoPoint geoPoint) {
MapPosition mapPosition = new MapPosition(geoPoint, mMapViewPosition.getZoomLevel(), 1);
MapPosition mapPosition = new MapPosition(geoPoint,
mMapViewPosition.getZoomLevel(), 1);
setCenterAndZoom(mapPosition);
}
@ -566,16 +569,22 @@ public class MapView extends GLSurfaceView {
protected final void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// find out how big the zoom controls should be
mMapZoomControls.measure(
MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.AT_MOST));
MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
MeasureSpec.AT_MOST));
// make sure that MapView is big enough to display the zoom controls
setMeasuredDimension(Math.max(MeasureSpec.getSize(widthMeasureSpec), mMapZoomControls.getMeasuredWidth()),
Math.max(MeasureSpec.getSize(heightMeasureSpec), mMapZoomControls.getMeasuredHeight()));
setMeasuredDimension(
Math.max(MeasureSpec.getSize(widthMeasureSpec),
mMapZoomControls.getMeasuredWidth()),
Math.max(MeasureSpec.getSize(heightMeasureSpec),
mMapZoomControls.getMeasuredHeight()));
}
@Override
protected synchronized void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
protected synchronized void onSizeChanged(int width, int height, int oldWidth,
int oldHeight) {
mMapWorker.pause();
mMapWorker.awaitPausing();
super.onSizeChanged(width, height, oldWidth, oldHeight);
@ -605,7 +614,8 @@ public class MapView extends GLSurfaceView {
* @return the maximum possible zoom level.
*/
byte getMaximumPossibleZoomLevel() {
return (byte) Math.min(mMapZoomControls.getZoomLevelMax(), mMapGenerator.getZoomLevelMax());
return (byte) Math.min(mMapZoomControls.getZoomLevelMax(),
mMapGenerator.getZoomLevelMax());
}
/**
@ -615,8 +625,9 @@ public class MapView extends GLSurfaceView {
if (!mMapViewPosition.isValid()) {
return false;
} else if (!mMapGenerator.requiresInternetConnection()
&& (!mMapDatabase.hasOpenFile() || !mMapDatabase.getMapFileInfo().boundingBox.contains(getMapPosition()
.getMapCenter()))) {
&& (!mMapDatabase.hasOpenFile() || !mMapDatabase.getMapFileInfo().boundingBox
.contains(getMapPosition()
.getMapCenter()))) {
return false;
}
@ -624,7 +635,8 @@ public class MapView extends GLSurfaceView {
}
byte limitZoomLevel(byte zoom) {
return (byte) Math.max(Math.min(zoom, getMaximumPossibleZoomLevel()), mMapZoomControls.getZoomLevelMin());
return (byte) Math.max(Math.min(zoom, getMaximumPossibleZoomLevel()),
mMapZoomControls.getZoomLevelMin());
}
@Override

View File

@ -222,11 +222,13 @@ public class DatabaseRenderer implements MapGenerator, RenderCallback,
mWays = wayLength;
if (!firstMatch && prevClosed == closed && !changed) {
DatabaseRenderer.renderTheme.matchWay(this, tags, mCurrentTile.zoomLevel,
DatabaseRenderer.renderTheme.matchWay(this, tags,
(byte) (mCurrentTile.zoomLevel + 0),
closed, false);
} else {
prevClosed = closed;
DatabaseRenderer.renderTheme.matchWay(this, tags, mCurrentTile.zoomLevel,
DatabaseRenderer.renderTheme.matchWay(this, tags,
(byte) (mCurrentTile.zoomLevel + 0),
closed, true);
}
@ -268,6 +270,9 @@ public class DatabaseRenderer implements MapGenerator, RenderCallback,
@Override
public void renderWay(Line line) {
// if (prevClosed && !mProjected)
// return;
projectToTile(false);
LineLayer outlineLayer = null;
@ -304,7 +309,7 @@ public class DatabaseRenderer implements MapGenerator, RenderCallback,
if (!mDebugDrawPolygons)
return;
// if (!projectToTile(mCurrentTile.zoomLevel < 13))
// if (!projectToTile(mCurrentTile.zoomLevel < 14))
if (!projectToTile(false))
return;

View File

@ -17,6 +17,7 @@ package org.mapsforge.android.glrenderer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import android.util.SparseArray;
@ -56,7 +57,8 @@ class LineLayers {
}
if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order(ByteOrder.nativeOrder());
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order(
ByteOrder.nativeOrder());
fbuf = bbuf.asFloatBuffer();
} else {
fbuf.position(0);
@ -87,8 +89,8 @@ class LineLayers {
return fbuf;
}
ByteBuffer compileLayerData(ByteBuffer buf) {
ByteBuffer sbuf = buf;
ShortBuffer compileLayerData(ShortBuffer buf) {
ShortBuffer sbuf = buf;
array = new LineLayer[layers.size()];
@ -98,14 +100,16 @@ class LineLayers {
size += l.verticesCnt * NUM_VERTEX_FLOATS;
}
if (buf == null || buf.capacity() < size * 2) {
sbuf = ByteBuffer.allocateDirect(size * 2).order(ByteOrder.nativeOrder());
if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 2).order(
ByteOrder.nativeOrder());
sbuf = bbuf.asShortBuffer();
} else {
sbuf.position(0);
}
int pos = 0;
byte[] data = new byte[PoolItem.SIZE * 2];
short[] data = new short[PoolItem.SIZE];
for (int i = 0, n = array.length; i < n; i++) {
LineLayer l = array[i];
@ -115,7 +119,7 @@ class LineLayers {
for (int k = 0, m = l.pool.size(); k < m; k++) {
PoolItem item = l.pool.get(k);
PoolItem.toHalfFloat(item, data);
sbuf.put(data, 0, item.used * 2);
sbuf.put(data, 0, item.used);
}
l.offset = pos;

View File

@ -14,8 +14,8 @@
*/
package org.mapsforge.android.glrenderer;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -88,7 +88,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
private long mTileX, mTileY;
private FloatBuffer floatBuffer = null;
private ByteBuffer byteBuffer = null;
// private ByteBuffer byteBuffer = null;
private ShortBuffer shortBuffer = null;
boolean useHalfFloat = false;
@ -125,7 +126,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
private int gLineTexturePositionHandle;
private int gLineColorHandle;
private int gLineMatrixHandle;
private int gLineWidthHandle;
private int gLineModeHandle;
private int gPolygonProgram;
@ -325,7 +325,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
newTiles.tiles[tiles++] = tile;
if (!tile.isDrawn && !tile.isLoading) {
MapGeneratorJob job = new MapGeneratorJob(tile, mapGenerator, mJobParameter, mDebugSettings);
MapGeneratorJob job = new MapGeneratorJob(tile, mapGenerator,
mJobParameter, mDebugSettings);
mJobList.add(job);
}
}
@ -395,8 +396,10 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
byte zoomLevel = mMapPosition.zoomLevel;
float scale = mMapPosition.scale;
double x = MercatorProjection.longitudeToPixelX(mMapPosition.geoPoint.getLongitude(), zoomLevel);
double y = MercatorProjection.latitudeToPixelY(mMapPosition.geoPoint.getLatitude(), zoomLevel);
double x = MercatorProjection.longitudeToPixelX(
mMapPosition.geoPoint.getLongitude(), zoomLevel);
double y = MercatorProjection.latitudeToPixelY(
mMapPosition.geoPoint.getLatitude(), zoomLevel);
long tileX = MercatorProjection.pixelXToTileX(x, zoomLevel);
long tileY = MercatorProjection.pixelYToTileY(y, zoomLevel);
@ -459,8 +462,10 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
blend = false;
}
GLES20.glUniform4f(gPolygonColorHandle, (color >> 16 & 0xff) / 255f * alpha, (color >> 8 & 0xff) / 255f
* alpha, (color & 0xff) / 255f * alpha, alpha);
GLES20.glUniform4f(gPolygonColorHandle,
(color >> 16 & 0xff) / 255f * alpha,
(color >> 8 & 0xff) / 255f * alpha,
(color & 0xff) / 255f * alpha, alpha);
// set stencil buffer mask used to draw this layer
GLES20.glStencilFunc(GLES20.GL_EQUAL, 0xff, 1 << c);
@ -486,10 +491,12 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id);
if (useHalfFloat) {
GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2, OES_HALF_FLOAT, false, 0,
GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
OES_HALF_FLOAT, false, 0,
POLYGON_VERTICES_DATA_POS_OFFSET);
} else {
GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2, GLES20.GL_FLOAT, false, 0,
GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
GLES20.GL_FLOAT, false, 0,
POLYGON_VERTICES_DATA_POS_OFFSET);
}
@ -531,11 +538,11 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
else {
// clear stencilbuffer
GLES20.glStencilMask(0xFF);
GLES20.glClear(GLES20.GL_STENCIL_BUFFER_BIT);
// GLES20.glClear(GLES20.GL_STENCIL_BUFFER_BIT);
// clear stencilbuffer (tile region)
// GLES20.glStencilOp(GLES20.GL_ZERO, GLES20.GL_ZERO, GLES20.GL_ZERO);
// GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glStencilOp(GLES20.GL_ZERO, GLES20.GL_ZERO, GLES20.GL_ZERO);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
// stencil op for stencil method polygon drawing
@ -554,7 +561,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
// modify alpha channel
float s = (mDrawScale < 1.3f ? 1.3f : mDrawScale);
colors[cnt] = (colors[cnt] & 0xffffff) | (byte) ((s - 1) * 0xff) << 24;
colors[cnt] = (colors[cnt] & 0xffffff)
| (byte) ((s - 1) * 0xff) << 24;
}
}
@ -588,16 +596,20 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.id);
if (useHalfFloat) {
GLES20.glVertexAttribPointer(gLineVertexPositionHandle, 2, OES_HALF_FLOAT, false, 8,
GLES20.glVertexAttribPointer(gLineVertexPositionHandle, 2, OES_HALF_FLOAT,
false, 8,
LINE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(gLineTexturePositionHandle, 2, OES_HALF_FLOAT, false, 8,
GLES20.glVertexAttribPointer(gLineTexturePositionHandle, 2, OES_HALF_FLOAT,
false, 8,
LINE_VERTICES_DATA_TEX_OFFSET >> 1);
} else {
GLES20.glVertexAttribPointer(gLineVertexPositionHandle, 2, GLES20.GL_FLOAT, false, 16,
GLES20.glVertexAttribPointer(gLineVertexPositionHandle, 2, GLES20.GL_FLOAT,
false, 16,
LINE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(gLineTexturePositionHandle, 2, GLES20.GL_FLOAT, false, 16,
GLES20.glVertexAttribPointer(gLineTexturePositionHandle, 2, GLES20.GL_FLOAT,
false, 16,
LINE_VERTICES_DATA_TEX_OFFSET);
}
@ -629,6 +641,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
// linear scale for fixed lines
float fdiv = 0.9f / (mDrawScale / z);
// int cnt = 0;
for (int i = 0, n = layers.length; i < n; i++) {
LineLayer l = layers[i];
@ -637,14 +650,16 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
drawOutlines = l.isOutline;
drawFixed = l.isFixed;
if (drawFixed) {
GLES20.glUniform1i(gLineModeHandle, 2);
GLES20.glUniform1f(gLineWidthHandle, fdiv);
GLES20.glUniform2f(gLineModeHandle, 0.4f, fdiv);
// GLES20.glUniform1f(gLineWidthHandle, fdiv);
} else if (drawOutlines) {
GLES20.glUniform1i(gLineModeHandle, 1);
GLES20.glUniform1f(gLineWidthHandle, wdiv);
GLES20.glUniform2f(gLineModeHandle, 0, wdiv);
// GLES20.glUniform1i(gLineModeHandle, 1);
// GLES20.glUniform1f(gLineWidthHandle, wdiv);
} else {
GLES20.glUniform1i(gLineModeHandle, 0);
GLES20.glUniform1f(gLineWidthHandle, wdiv * 0.95f);
GLES20.glUniform2f(gLineModeHandle, 0, wdiv * 0.95f);
// GLES20.glUniform1i(gLineModeHandle, 0);
// GLES20.glUniform1f(gLineWidthHandle, wdiv * 0.95f);
}
}
@ -659,7 +674,12 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
} else {
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
}
// cnt += l.verticesCnt;
}
// GLES20.glUniform2f(gLineModeHandle, 0, wdiv);
// float[] c = { 1, 0, 0, 1 };
// GLES20.glUniform4fv(gLineColorHandle, 1, c, 0);
// GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, cnt);
return true;
}
@ -754,7 +774,15 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
}
}
private int uploadCnt;
private boolean uploadTileData(GLMapTile tile) {
// not sure about this, but seems it fixes some flickering when
// multiple tiles are uploaded in one go. but if this is really
// the issue tiles should stay corrupted..
if (uploadCnt++ > 0)
GLES20.glFinish();
if (tile.lineVBO == null) {
// Upload line data to vertex buffer object
synchronized (mVBOs) {
@ -766,7 +794,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
}
}
if (useHalfFloat)
byteBuffer = tile.lineLayers.compileLayerData(byteBuffer);
shortBuffer = tile.lineLayers.compileLayerData(shortBuffer);
else
floatBuffer = tile.lineLayers.compileLayerData(floatBuffer);
@ -778,10 +806,12 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
if (useHalfFloat) {
tile.lineVBO.size = tile.lineLayers.size * SHORT_BYTES;
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.size, byteBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.size,
shortBuffer, GLES20.GL_STATIC_DRAW);
} else {
tile.lineVBO.size = tile.lineLayers.size * FLOAT_BYTES;
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.size, floatBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.size,
floatBuffer, GLES20.GL_STATIC_DRAW);
}
mBufferMemoryUsage += tile.lineVBO.size;
@ -791,7 +821,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
}
if (useHalfFloat)
byteBuffer = tile.polygonLayers.compileLayerData(byteBuffer);
shortBuffer = tile.polygonLayers.compileLayerData(shortBuffer);
else
floatBuffer = tile.polygonLayers.compileLayerData(floatBuffer);
@ -804,10 +834,12 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
if (useHalfFloat) {
tile.polygonVBO.size = tile.polygonLayers.size * SHORT_BYTES;
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size, byteBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size,
shortBuffer, GLES20.GL_STATIC_DRAW);
} else {
tile.polygonVBO.size = tile.polygonLayers.size * FLOAT_BYTES;
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size, floatBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size,
floatBuffer, GLES20.GL_STATIC_DRAW);
}
mBufferMemoryUsage += tile.polygonVBO.size;
@ -835,7 +867,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
GLES20.glStencilMask(0xFF);
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT);
GLES20.glFlush();
synchronized (this) {
mDrawX = mCurX;
mDrawY = mCurY;
@ -854,14 +886,16 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
GLMapTile[] tiles = curTiles.tiles;
if (mBufferMemoryUsage > LIMIT_BUFFERS) {
Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / (1024 * 1024) + "MB");
Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / (1024 * 1024)
+ "MB");
synchronized (mVBOs) {
for (VertexBufferObject vbo : mVBOs) {
if (vbo.size == 0)
continue;
mBufferMemoryUsage -= vbo.size;
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null, GLES20.GL_STATIC_DRAW);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null,
GLES20.GL_STATIC_DRAW);
vbo.size = 0;
}
@ -869,6 +903,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
Log.d(TAG, " > " + mBufferMemoryUsage / (1024 * 1024) + "MB");
}
uploadCnt = 0;
// check visible tiles, set tile clip scissors, upload new vertex data
for (int i = 0; i < tileCnt; i++) {
GLMapTile tile = tiles[i];
@ -880,7 +916,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
uploadTileData(tile);
if (timing)
Log.d(TAG, "buffer upload took: " + (SystemClock.uptimeMillis() - start));
Log.d(TAG, "buffer upload took: "
+ (SystemClock.uptimeMillis() - start));
continue;
}
@ -901,6 +938,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
}
}
}
// GLES20.glFinish();
if (timing)
clear_time = (SystemClock.uptimeMillis() - start);
@ -930,7 +968,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
GLES20.glFinish();
poly_time = (SystemClock.uptimeMillis() - start);
}
// GLES20.glFlush();
// Draw lines
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glUseProgram(gLineProgram);
@ -946,11 +984,12 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
}
}
// GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
if (timing) {
GLES20.glFinish();
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start) + " " + clear_time + " " + poly_time);
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start) + " "
+ clear_time + " " + poly_time);
}
}
@ -1002,10 +1041,12 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Set up the program for rendering lines
gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader, Shaders.gLineFragmentShader);
gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
Shaders.gLineFragmentShader);
if (gLineProgram == 0) {
Log.e(TAG, "trying simple line program.");
gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader, Shaders.gLineFragmentShaderSimple);
gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
Shaders.gLineFragmentShaderSimple);
if (gLineProgram == 0) {
Log.e(TAG, "Could not create line program.");
return;
@ -1020,20 +1061,22 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
Log.d(TAG, "Extensions: " + ext);
gLineMatrixHandle = GLES20.glGetUniformLocation(gLineProgram, "u_center");
gLineWidthHandle = GLES20.glGetUniformLocation(gLineProgram, "u_width");
gLineModeHandle = GLES20.glGetUniformLocation(gLineProgram, "u_mode");
gLineColorHandle = GLES20.glGetUniformLocation(gLineProgram, "u_color");
gLineVertexPositionHandle = GLES20.glGetAttribLocation(gLineProgram, "a_position");
gLineVertexPositionHandle = GLES20
.glGetAttribLocation(gLineProgram, "a_position");
gLineTexturePositionHandle = GLES20.glGetAttribLocation(gLineProgram, "a_st");
// Set up the program for rendering polygons
gPolygonProgram = GlUtils.createProgram(Shaders.gPolygonVertexShader, Shaders.gPolygonFragmentShader);
gPolygonProgram = GlUtils.createProgram(Shaders.gPolygonVertexShader,
Shaders.gPolygonFragmentShader);
if (gPolygonProgram == 0) {
Log.e(TAG, "Could not create polygon program.");
return;
}
gPolygonMatrixHandle = GLES20.glGetUniformLocation(gPolygonProgram, "u_center");
gPolygonVertexPositionHandle = GLES20.glGetAttribLocation(gPolygonProgram, "a_position");
gPolygonVertexPositionHandle = GLES20.glGetAttribLocation(gPolygonProgram,
"a_position");
gPolygonColorHandle = GLES20.glGetUniformLocation(gPolygonProgram, "u_color");
GLES20.glUseProgram(gPolygonProgram);

View File

@ -16,11 +16,14 @@ package org.mapsforge.android.glrenderer;
import java.util.LinkedList;
import org.mapsforge.core.Tile;
class PolygonLayer extends Layer {
int fadeLevel;
private boolean first = true;
private float originX;
private float originY;
// private boolean first = true;
// private float originX;
// private float originY;
PolygonLayer(int layer, int color, int fade) {
super(layer, color);
@ -34,11 +37,11 @@ class PolygonLayer extends Layer {
verticesCnt += length / 2 + 2;
if (first) {
first = false;
originX = points[pos];
originY = points[pos + 1];
}
// if (first) {
// first = false;
// originX = points[pos];
// originY = points[pos + 1];
// }
float[] curVertices = curItem.vertices;
int outPos = curItem.used;
@ -48,8 +51,8 @@ class PolygonLayer extends Layer {
outPos = 0;
}
curVertices[outPos++] = originX;
curVertices[outPos++] = originY;
curVertices[outPos++] = Tile.TILE_SIZE >> 1;
curVertices[outPos++] = Tile.TILE_SIZE >> 1;
int remaining = length;
int inPos = pos;
@ -74,7 +77,7 @@ class PolygonLayer extends Layer {
curVertices = getNextItem();
outPos = 0;
}
// Float.intBitsToFloat(bits)
curVertices[outPos++] = points[pos + 0];
curVertices[outPos++] = points[pos + 1];

View File

@ -17,6 +17,7 @@ package org.mapsforge.android.glrenderer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import org.mapsforge.android.utils.FastMath;
import org.mapsforge.core.Tile;
@ -25,10 +26,11 @@ import android.util.SparseArray;
class PolygonLayers {
private static final int NUM_VERTEX_FLOATS = 2;
private static final float[] mFillCoords = { -2, Tile.TILE_SIZE + 1, Tile.TILE_SIZE + 1, Tile.TILE_SIZE + 1, -2,
private static final float[] mFillCoords = { -2, Tile.TILE_SIZE + 1,
Tile.TILE_SIZE + 1, Tile.TILE_SIZE + 1, -2,
-2, Tile.TILE_SIZE + 1, -2 };
private static byte[] mByteFillCoords = null;
private static short[] mByteFillCoords = null;
private SparseArray<PolygonLayer> layers;
@ -68,7 +70,8 @@ class PolygonLayers {
size *= NUM_VERTEX_FLOATS;
if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order(ByteOrder.nativeOrder());
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order(
ByteOrder.nativeOrder());
// Log.d("GLMap", "allocate buffer " + size);
fbuf = bbuf.asFloatBuffer();
} else {
@ -100,8 +103,8 @@ class PolygonLayers {
return fbuf;
}
ByteBuffer compileLayerData(ByteBuffer buf) {
ByteBuffer bbuf = buf;
ShortBuffer compileLayerData(ShortBuffer buf) {
ShortBuffer sbuf = buf;
array = new PolygonLayer[layers.size()];
@ -113,27 +116,29 @@ class PolygonLayers {
size *= NUM_VERTEX_FLOATS;
if (buf == null || buf.capacity() < size * 2) {
bbuf = ByteBuffer.allocateDirect(size * 2).order(ByteOrder.nativeOrder());
if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 2).order(
ByteOrder.nativeOrder());
sbuf = bbuf.asShortBuffer();
} else {
bbuf.position(0);
sbuf.position(0);
}
byte[] data = new byte[PoolItem.SIZE * 2];
short[] data = new short[PoolItem.SIZE];
if (mByteFillCoords == null) {
mByteFillCoords = new byte[16];
mByteFillCoords = new short[8];
FastMath.convertFloatToHalf(mFillCoords[0], mByteFillCoords, 0);
FastMath.convertFloatToHalf(mFillCoords[1], mByteFillCoords, 2);
FastMath.convertFloatToHalf(mFillCoords[2], mByteFillCoords, 4);
FastMath.convertFloatToHalf(mFillCoords[3], mByteFillCoords, 6);
FastMath.convertFloatToHalf(mFillCoords[4], mByteFillCoords, 8);
FastMath.convertFloatToHalf(mFillCoords[5], mByteFillCoords, 10);
FastMath.convertFloatToHalf(mFillCoords[6], mByteFillCoords, 12);
FastMath.convertFloatToHalf(mFillCoords[7], mByteFillCoords, 14);
FastMath.convertFloatToHalf(mFillCoords[1], mByteFillCoords, 1);
FastMath.convertFloatToHalf(mFillCoords[2], mByteFillCoords, 2);
FastMath.convertFloatToHalf(mFillCoords[3], mByteFillCoords, 3);
FastMath.convertFloatToHalf(mFillCoords[4], mByteFillCoords, 4);
FastMath.convertFloatToHalf(mFillCoords[5], mByteFillCoords, 5);
FastMath.convertFloatToHalf(mFillCoords[6], mByteFillCoords, 6);
FastMath.convertFloatToHalf(mFillCoords[7], mByteFillCoords, 7);
}
bbuf.put(mByteFillCoords, 0, 16);
sbuf.put(mByteFillCoords, 0, 8);
int pos = 4;
for (int i = 0, n = array.length; i < n; i++) {
@ -142,7 +147,7 @@ class PolygonLayers {
for (int k = 0, m = l.pool.size(); k < m; k++) {
PoolItem item = l.pool.get(k);
PoolItem.toHalfFloat(item, data);
bbuf.put(data, 0, item.used * 2);
sbuf.put(data, 0, item.used);
}
l.offset = pos;
@ -152,11 +157,11 @@ class PolygonLayers {
l.pool = null;
}
bbuf.position(0);
sbuf.position(0);
// not needed for drawing
layers = null;
return bbuf;
return sbuf;
}
}

View File

@ -15,74 +15,79 @@
package org.mapsforge.android.glrenderer;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
// TODO use byte[] for half-float, not converting on compilation (in glThread)
class PoolItem {
final float[] vertices;
// final byte[] vertices;
int used;
PoolItem() {
vertices = new float[SIZE];
// vertices = new byte[SIZE];
used = 0;
}
static int SIZE = 256;
private static final byte b0x7c = (byte) 0x7c;
private static final byte b0x00 = (byte) 0x00;
private static final byte b0x01 = (byte) 0x01;
private static final byte b0xfc = (byte) 0xfc;
private static final byte b0x80 = (byte) 0x80;
private static final byte b0x7b = (byte) 0x7b;
private static final byte b0xff = (byte) 0xff;
private static final byte b0xfb = (byte) 0xfb;
private static final float FLOAT_HALF_PREC = 5.96046E-8f;
private static final float FLOAT_HALF_MAX = 65504f;
static void toHalfFloat(PoolItem item, byte[] data) {
private static ByteBuffer byteBuffer = ByteBuffer.allocate(SIZE * 4);
private static IntBuffer intBuffer = byteBuffer.asIntBuffer();
private static FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
private static int[] intArray = new int[SIZE];
static void toHalfFloat(PoolItem item, short[] data) {
floatBuffer.position(0);
floatBuffer.put(item.vertices, 0, item.used);
intBuffer.position(0);
intBuffer.get(intArray, 0, item.used);
int out = 0;
for (int j = 0; j < item.used; j++) {
float flt = item.vertices[j];
int f = intArray[j];
if (flt == 0f) {
data[out++] = b0x00;
data[out++] = b0x00;
} else if (flt == -0f) {
data[out++] = b0x00;
data[out++] = b0x80;
if (f == 0x0000000) {
// == 0
data[out++] = (short) 0x0000;
} else if (f == 0x80000000) {
// == -0
data[out++] = (short) 0x8000;
} else if (f == 0x3f800000) {
// == 1
data[out++] = (short) 0x3c00;
} else if (f == 0xbf800000) {
// == -1
data[out++] = (short) 0xbc00;
} else if (flt > FLOAT_HALF_MAX) {
if (flt == Float.POSITIVE_INFINITY) {
data[out++] = b0x00;
data[out++] = b0x7c;
data[out++] = (short) 0x7c00;
} else {
data[out++] = b0xff;
data[out++] = b0x7b;
data[out++] = (short) 0x7bff;
}
} else if (flt < -FLOAT_HALF_MAX) {
if (flt == Float.NEGATIVE_INFINITY) {
data[out++] = b0x00;
data[out++] = b0xfc;
data[out++] = (short) 0xfc00;
} else {
data[out++] = b0xff;
data[out++] = b0xfb;
data[out++] = (short) 0xfbff;
}
} else if (flt > 0f && flt < FLOAT_HALF_PREC) {
data[out++] = b0x01;
data[out++] = b0x00;
data[out++] = (short) 0x0001;
} else if (flt < 0f && flt > -FLOAT_HALF_PREC) {
data[out++] = b0x01;
data[out++] = b0x80;
data[out++] = (short) 0x8001;
} else {
int f = Float.floatToIntBits(flt);
// maybe just ignore and set 0? -- we'll see. when this happens
if (f == 0x7fc00000)
throw new UnsupportedOperationException("NaN to half conversion not supported!");
throw new UnsupportedOperationException(
"NaN to half conversion not supported!");
data[out++] = (byte) ((f >> 13) & 0xff);
data[out++] = (byte) (((f >> 24) & 0x80) | ((((f & 0x7f800000) - 0x38000000) >> 21) & 0x7c) | ((f >> 21) & 0x03));
data[out++] = (short) (((f >> 16) & 0x8000)
| ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00)
| ((f >> 13) & 0x03ff));
}
}
}

View File

@ -17,60 +17,78 @@ package org.mapsforge.android.glrenderer;
class Shaders {
final static String gLineVertexShader = ""
+ "precision highp float; \n"
+ "precision mediump float; \n"
+ "uniform mat4 u_center;"
+ "uniform float u_width;"
// + "uniform float u_width;"
+ "attribute vec4 a_position;"
+ "attribute vec2 a_st;"
+ "varying vec2 v_st;"
+ "void main() {"
+ " gl_Position = u_center * a_position;"
+ " v_st = a_st;" + "}";
+ " v_st = a_st;"
+ "}";
final static String gLineFragmentShader = ""
+ "#extension GL_OES_standard_derivatives : enable\n"
+ "precision mediump float;"
+ "uniform float u_width;"
+ "uniform int u_mode;"
+ "uniform vec2 u_mode;"
+ "uniform vec4 u_color;"
+ "const float zero = 0.0;"
+ "const int standard = 0;"
+ "const int fixed_width = 2;"
+ "const vec4 blank = vec4(1.0, 0.0, 0.0, 1.0);"
+ "const vec4 blank2 = vec4(0.0, 1.0, 0.0, 1.0);"
+ "varying vec2 v_st;"
+ "void main() {"
+ " if (u_mode != fixed_width) {"
// + " gl_FragColor = u_color;"
// + " float fuzz;"
// + " float len;"
+ " if (v_st.t == zero){ "
// + " fuzz = - sqrt(dFdx(v_st.s) * dFdx(v_st.s) + dFdy(v_st.s) * dFdy(v_st.s));"
+ " float fuzz = -fwidth(v_st.s) * 1.5;"
+ " float len = abs(v_st.s) - u_width;"
// + " if (len < fuzz)"
+ " gl_FragColor = u_color * smoothstep(zero, fuzz, len);"
+ " } else {"
+ " float fuzz = -max(fwidth(v_st.s), fwidth(v_st.t)) * 1.5;"
+ " float len = length(v_st) - u_width;"
// + " if (len < fuzz)"
+ " gl_FragColor = u_color * smoothstep(zero, fuzz, len);"
+ " } "
// + " if (len > zero)"
// + " gl_FragColor = blank;"
// + " discard;"
// + " gl_FragColor = u_color;"
// + " else if (len < fuzz)"
// + " gl_FragColor = blank2;"
// + " else "
+ " } else { "
+ " float fuzz = fwidth(v_st.s);"
// + " gl_FragColor = u_color * smoothstep(fuzz, zero, abs(v_st.s) - u_width + fuzz);"
// + " fuzz = - sqrt(dFdx(v_st.s) * dFdx(v_st.s) + dFdy(v_st.s) * dFdy(v_st.s)) * 1.5;"
+ " gl_FragColor = u_color * smoothstep(fuzz*0.5, -fuzz, abs(v_st.s) - u_width);"
+ " }"
+ "float width = u_mode[1];"
// + " if (v_st.t == zero){ "
// + " float fuzz = fwidth(v_st.s) * 1.5;"
// + " gl_FragColor = u_color * smoothstep(-fuzz * u_mode[0], fuzz, width - abs(v_st.s));"
// + " } else {"
+ " float fuzz = max(fwidth(v_st.s), fwidth(v_st.t)) * 1.5;"
+ " gl_FragColor = u_color * smoothstep(-fuzz * u_mode[0], fuzz, width - length(v_st));"
// + " } "
+ "}";
// final static String gLineFragmentShader = ""
// + "#extension GL_OES_standard_derivatives : enable\n"
// + "precision mediump float;"
// + "uniform float u_width;"
// + "uniform vec2 u_mode;"
// + "uniform vec4 u_color;"
// + "const float zero = 0.0;"
// // + "const vec4 blank = vec4(1.0, 0.0, 0.0, 1.0);"
// + "varying vec2 v_st;"
// + "void main() {"
// + "float width = u_mode[1];"
// // + "float alpha = 1.0;"
// + " if (u_mode[0] == zero) {"
// // + " gl_FragColor = u_color;"
// // + " float fuzz;"
// // + " float len;"
// + " if (v_st.t == zero){ "
// // + " fuzz = - sqrt(dFdx(v_st.s) * dFdx(v_st.s) + dFdy(v_st.s) * dFdy(v_st.s));"
// + " float fuzz = -fwidth(v_st.s) * 1.5;"
// + " float len = abs(v_st.s) - width;"
// // + " if (len < fuzz)"
// + " gl_FragColor = u_color * smoothstep(zero, fuzz, len);"
// + " } else {"
// + " float fuzz = -max(fwidth(v_st.s), fwidth(v_st.t)) * 1.5;"
// + " float len = length(v_st) - width;"
// // + " if (len < fuzz)"
// + " gl_FragColor = u_color * smoothstep(zero, fuzz, len);"
// + " } "
// // + " if (len > zero)"
// // + " gl_FragColor = blank;"
// // + " discard;"
// // + " gl_FragColor = u_color;"
// // + " else if (len < fuzz)"
// // + " gl_FragColor = blank2;"
// // + " else "
// + " } else { "
// + " float fuzz = fwidth(v_st.s);"
// // + " gl_FragColor = u_color * smoothstep(fuzz, zero, abs(v_st.s) - u_width + fuzz);"
// // + " fuzz = - sqrt(dFdx(v_st.s) * dFdx(v_st.s) + dFdy(v_st.s) * dFdy(v_st.s)) * 1.5;"
// + " gl_FragColor = u_color * smoothstep(fuzz*0.5, -fuzz, abs(v_st.s) - width);"
// + " }"
// + "}";
// final static String gLineFragmentShader = "" +
// "#extension GL_OES_standard_derivatives : enable\n" +
// "precision mediump float;" +

View File

@ -208,7 +208,7 @@
<rule e="way" k="waterway" v="*">
<rule e="way" k="waterway" v="ditch|drain" zoom-min="14">
<line stroke="#b4cbdc" stroke-width="0.5" stroke-linecap="butt"
<line stroke="#b4cbdc" stroke-width="0.7" stroke-linecap="butt"
fixed="true" />
</rule>
@ -332,7 +332,7 @@
<rule e="way" k="outline" v="*">
<rule e="way" k="*" v="1">
<outline stroke="#909090" />
<outline stroke="#bb909090" />
</rule>
<rule e="way" k="*" v="2">
<outline stroke="#c0c0c0" />
@ -401,14 +401,10 @@
<line stroke="#d3cb98" stroke-width="0.4" outline="2" />
</rule>
<rule e="way" k="*" v="service|byway">
<rule e="way" k="*" v="service|byway|pedestrian">
<line stroke="#ffffff" stroke-width="0.8" outline="1" />
</rule>
<rule e="way" k="*" v="pedestrian">
<line stroke="#f1f0f4" stroke-width="0.8" outline="1" />
</rule>
<rule e="way" k="*" v="construction">
<line stroke="#d0d0d0" stroke-width="1.3" outline="1" />
</rule>
@ -418,9 +414,7 @@
<rule e="way" k="*" v="residential|road|unclassified|living_street">
<rule e="way" k="bridge" v="yes|true">
<line stroke="#ffffff" stroke-width="1.3" stroke-linecap="butt"
outline="2" />
<line stroke="#ffffff" stroke-width="1.3" outline="2" stroke-linecap="butt" />
</rule>
<rule e="way" k="bridge" v="~|no|false">
<line stroke="#ffffff" stroke-width="1.3" outline="1" />
@ -434,19 +428,17 @@
<rule e="way" k="*" v="*" zoom-min="11">
<rule e="way" k="*" v="tertiary|secondary_link">
<line stroke="#ffff9a" stroke-width="1.5" outline="3" />
<line stroke="#ffffff" stroke-width="1.5" outline="1" />
</rule>
<rule e="way" k="*" v="trunk_link|motorway_link">
<line stroke="#fed6a3" stroke-width="1.6" stroke-linecap="butt"
outline="4" />
<line stroke="#fed6a3" stroke-width="1.5" outline="4" stroke-linecap="butt" />
</rule>
<rule e="way" k="*" v="secondary|primary_link">
<rule e="way" k="bridge" v="yes|true">
<line stroke="#fefe8a" stroke-width="1.6" outline="1"
stroke-linecap="butt" />
<line stroke="#fefe8a" stroke-width="1.6" outline="1" stroke-linecap="butt" />
</rule>
<rule e="way" k="bridge" v="~|no|false">
@ -455,18 +447,15 @@
</rule>
<rule e="way" k="*" v="primary">
<line stroke="#fefe8a" stroke-width="1.7" stroke-linecap="butt"
outline="3" />
<line stroke="#fefe8a" stroke-width="1.7" outline="3" stroke-linecap="butt" />
</rule>
<rule e="way" k="*" v="trunk">
<line stroke="#fed6a3" stroke-width="1.8" stroke-linecap="butt"
outline="4" />
<line stroke="#fed6a3" stroke-width="1.8" outline="4" stroke-linecap="butt" />
</rule>
<rule e="way" k="*" v="motorway">
<line stroke="#eec693" stroke-width="1.9" stroke-linecap="butt"
outline="4" />
<line stroke="#eec693" stroke-width="1.9" outline="4" stroke-linecap="butt" />
</rule>
</rule>
</rule>

View File

@ -1,8 +1,7 @@
package org.mapsforge.android.utils;
/**
* Copyright (c) 2009-2010 jMonkeyEngine
* All rights reserved. FastMath.java
* Copyright (c) 2009-2010 jMonkeyEngine All rights reserved. FastMath.java
*/
public class FastMath {
@ -58,7 +57,8 @@ public class FastMath {
int f = Float.floatToIntBits(flt);
if (f == 0x7fc00000)
throw new UnsupportedOperationException("NaN to half conversion not supported!");
throw new UnsupportedOperationException(
"NaN to half conversion not supported!");
data[pos + 1] = (byte) (((f >> 24) & 0x80)
| ((((f & 0x7f800000) - 0x38000000) >> 21) & 0x7c)
@ -67,4 +67,50 @@ public class FastMath {
data[pos + 0] = (byte) ((f >> 13) & 0xff);
}
}
/**
* @param flt
* ...
* @param data
* ...
* @param pos
* ..
*/
public static void convertFloatToHalf(float flt, short[] data, int pos) {
if (flt == 0f) {
data[pos] = (short) 0x0000;
} else if (flt == -0f) {
data[pos] = (short) 0x8000;
} else if (flt == 1f) {
data[pos] = (short) 0x3c00;
} else if (flt == -1f) {
data[pos] = (short) 0xbc00;
} else if (flt > FLOAT_HALF_MAX) {
if (flt == Float.POSITIVE_INFINITY) {
data[pos] = (short) 0x7c00;
} else {
data[pos] = (short) 0x7bff;
}
} else if (flt < -FLOAT_HALF_MAX) {
if (flt == Float.NEGATIVE_INFINITY) {
data[pos] = (short) 0xfc00;
} else {
data[pos] = (short) 0xfbff;
}
} else if (flt > 0f && flt < FLOAT_HALF_PREC) {
data[pos] = (short) 0x0001;
} else if (flt < 0f && flt > -FLOAT_HALF_PREC) {
data[pos] = (short) 0x8001;
} else {
int f = Float.floatToIntBits(flt);
if (f == 0x7fc00000)
throw new UnsupportedOperationException(
"NaN to half conversion not supported!");
data[pos] = (short) (((f >> 16) & 0x8000)
| ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00)
| ((f >> 13) & 0x03ff));
}
}
}

View File

@ -14,7 +14,6 @@
*/
package org.mapsforge.core;
/**
* A tile represents a rectangular part of the world map. All tiles can be identified by their X and Y number together
* with their zoom level. The actual area that a tile covers on a map depends on the underlying map projection.
@ -33,7 +32,8 @@ public class Tile {
/**
* Size of a single uncompressed map tile bitmap in bytes.
*/
public static final int TILE_SIZE_IN_BYTES = TILE_SIZE * TILE_SIZE * TILE_BYTES_PER_PIXEL;
public static final int TILE_SIZE_IN_BYTES = TILE_SIZE * TILE_SIZE
* TILE_BYTES_PER_PIXEL;
/**
* The X number of this tile.

View File

@ -254,11 +254,14 @@ public class MapDatabase implements IMapDatabase {
try {
prepareExecution();
QueryParameters queryParameters = new QueryParameters();
queryParameters.queryZoomLevel = mMapFileHeader.getQueryZoomLevel(tile.zoomLevel);
queryParameters.queryZoomLevel = mMapFileHeader
.getQueryZoomLevel(tile.zoomLevel);
// get and check the sub-file for the query zoom level
SubFileParameter subFileParameter = mMapFileHeader.getSubFileParameter(queryParameters.queryZoomLevel);
SubFileParameter subFileParameter = mMapFileHeader
.getSubFileParameter(queryParameters.queryZoomLevel);
if (subFileParameter == null) {
LOG.warning("no sub-file for zoom level: " + queryParameters.queryZoomLevel);
LOG.warning("no sub-file for zoom level: "
+ queryParameters.queryZoomLevel);
return;
}
@ -320,7 +323,8 @@ public class MapDatabase implements IMapDatabase {
mReadBuffer = new ReadBuffer(mInputFile);
mMapFileHeader = new MapFileHeader();
FileOpenResult fileOpenResult = mMapFileHeader.readHeader(mReadBuffer, mFileSize);
FileOpenResult fileOpenResult = mMapFileHeader.readHeader(mReadBuffer,
mFileSize);
if (!fileOpenResult.isSuccess()) {
closeFile();
return fileOpenResult;
@ -361,7 +365,8 @@ public class MapDatabase implements IMapDatabase {
* @param mapDatabaseCallback
* the callback which handles the extracted map elements.
*/
private void processBlock(QueryParameters queryParameters, SubFileParameter subFileParameter,
private void processBlock(QueryParameters queryParameters,
SubFileParameter subFileParameter,
IMapDatabaseCallback mapDatabaseCallback) {
if (!processBlockSignature()) {
return;
@ -416,7 +421,8 @@ public class MapDatabase implements IMapDatabase {
}
private void processBlocks(IMapDatabaseCallback mapDatabaseCallback, QueryParameters queryParameters,
private void processBlocks(IMapDatabaseCallback mapDatabaseCallback,
QueryParameters queryParameters,
SubFileParameter subFileParameter) throws IOException {
boolean queryIsWater = true;
// boolean queryReadWaterInfo = false;
@ -429,7 +435,8 @@ public class MapDatabase implements IMapDatabase {
long blockNumber = row * subFileParameter.blocksWidth + column;
// get the current index entry
long currentBlockIndexEntry = mDatabaseIndexCache.getIndexEntry(subFileParameter, blockNumber);
long currentBlockIndexEntry = mDatabaseIndexCache.getIndexEntry(
subFileParameter, blockNumber);
// check if the current query would still return a water tile
if (queryIsWater) {
@ -440,7 +447,8 @@ public class MapDatabase implements IMapDatabase {
// get and check the current block pointer
long currentBlockPointer = currentBlockIndexEntry & BITMASK_INDEX_OFFSET;
if (currentBlockPointer < 1 || currentBlockPointer > subFileParameter.subFileSize) {
if (currentBlockPointer < 1
|| currentBlockPointer > subFileParameter.subFileSize) {
LOG.warning("invalid current block pointer: " + currentBlockPointer);
LOG.warning("subFileSize: " + subFileParameter.subFileSize);
return;
@ -453,9 +461,11 @@ public class MapDatabase implements IMapDatabase {
nextBlockPointer = subFileParameter.subFileSize;
} else {
// get and check the next block pointer
nextBlockPointer = mDatabaseIndexCache.getIndexEntry(subFileParameter, blockNumber + 1)
nextBlockPointer = mDatabaseIndexCache.getIndexEntry(
subFileParameter, blockNumber + 1)
& BITMASK_INDEX_OFFSET;
if (nextBlockPointer < 1 || nextBlockPointer > subFileParameter.subFileSize) {
if (nextBlockPointer < 1
|| nextBlockPointer > subFileParameter.subFileSize) {
LOG.warning("invalid next block pointer: " + nextBlockPointer);
LOG.warning("sub-file size: " + subFileParameter.subFileSize);
return;
@ -465,7 +475,8 @@ public class MapDatabase implements IMapDatabase {
// calculate the size of the current block
int currentBlockSize = (int) (nextBlockPointer - currentBlockPointer);
if (currentBlockSize < 0) {
LOG.warning("current block size must not be negative: " + currentBlockSize);
LOG.warning("current block size must not be negative: "
+ currentBlockSize);
return;
} else if (currentBlockSize == 0) {
// the current block is empty, continue with the next block
@ -475,7 +486,8 @@ public class MapDatabase implements IMapDatabase {
LOG.warning("current block size too large: " + currentBlockSize);
continue;
} else if (currentBlockPointer + currentBlockSize > mFileSize) {
LOG.warning("current block largher than file size: " + currentBlockSize);
LOG.warning("current block largher than file size: "
+ currentBlockSize);
return;
}
@ -490,10 +502,12 @@ public class MapDatabase implements IMapDatabase {
}
// calculate the top-left coordinates of the underlying tile
double tileLatitudeDeg = MercatorProjection.tileYToLatitude(subFileParameter.boundaryTileTop + row,
double tileLatitudeDeg = MercatorProjection.tileYToLatitude(
subFileParameter.boundaryTileTop + row,
subFileParameter.baseZoomLevel);
double tileLongitudeDeg = MercatorProjection.tileXToLongitude(subFileParameter.boundaryTileLeft
+ column, subFileParameter.baseZoomLevel);
double tileLongitudeDeg = MercatorProjection.tileXToLongitude(
subFileParameter.boundaryTileLeft
+ column, subFileParameter.baseZoomLevel);
mTileLatitude = (int) (tileLatitudeDeg * 1000000);
mTileLongitude = (int) (tileLongitudeDeg * 1000000);
@ -544,7 +558,6 @@ public class MapDatabase implements IMapDatabase {
* @return true if the POIs could be processed successfully, false otherwise.
*/
private boolean processPOIs(IMapDatabaseCallback mapDatabaseCallback, int numberOfPois) {
// List<Tag> tags = new ArrayList<Tag>();
Tag[] poiTags = mMapFileHeader.getMapFileInfo().poiTags;
Tag[] tags = null;
@ -586,22 +599,19 @@ public class MapDatabase implements IMapDatabase {
byte featureByte = mReadBuffer.readByte();
// bit 1-3 enable optional features
boolean featureName = (featureByte & POI_FEATURE_NAME) != 0;
boolean featureHouseNumber = (featureByte & POI_FEATURE_HOUSE_NUMBER) != 0;
boolean featureElevation = (featureByte & POI_FEATURE_ELEVATION) != 0;
// check if the POI has a name
if (featureName) {
if ((featureByte & POI_FEATURE_NAME) != 0) {
mReadBuffer.getPositionAndSkip();
}
// check if the POI has a house number
if (featureHouseNumber) {
if ((featureByte & POI_FEATURE_HOUSE_NUMBER) != 0) {
mReadBuffer.getPositionAndSkip();
}
// check if the POI has an elevation
if (featureElevation) {
if ((featureByte & POI_FEATURE_ELEVATION) != 0) {
mReadBuffer.readSignedInt();
// mReadBuffer.getPositionAndSkip();// tags.add(new Tag(Tag.TAG_KEY_ELE,
// Integer.toString(mReadBuffer.readSignedInt())));
@ -686,7 +696,8 @@ public class MapDatabase implements IMapDatabase {
dLon = nLon - wayNodeLongitude;
wayNodeLongitude = nLon;
if (dLon > minLon || dLon < -minLon || dLat > minLat || dLat < -minLat || (pos == length - 2)) {
if (dLon > minLon || dLon < -minLon || dLat > minLat || dLat < -minLat
|| (pos == length - 2)) {
outBuffer[floatPos++] = nLon;
outBuffer[floatPos++] = nLat;
cnt += 2;
@ -727,7 +738,8 @@ public class MapDatabase implements IMapDatabase {
dLon = nLon - wayNodeLongitude;
wayNodeLongitude = nLon;
if (dLon > minLon || dLon < -minLon || dLat > minLat || dLat < -minLat || (pos == length - 2)) {
if (dLon > minLon || dLon < -minLon || dLat > minLat || dLat < -minLat
|| (pos == length - 2)) {
outBuffer[floatPos++] = nLon;
outBuffer[floatPos++] = nLat;
cnt += 2;
@ -760,7 +772,8 @@ public class MapDatabase implements IMapDatabase {
* how many ways should be processed.
* @return true if the ways could be processed successfully, false otherwise.
*/
private boolean processWays(QueryParameters queryParameters, IMapDatabaseCallback mapDatabaseCallback,
private boolean processWays(QueryParameters queryParameters,
IMapDatabaseCallback mapDatabaseCallback,
int numberOfWays) {
Tag[] tags = null;
@ -787,7 +800,8 @@ public class MapDatabase implements IMapDatabase {
}
if (queryParameters.useTileBitmask) {
elementCounter = mReadBuffer.skipWays(queryParameters.queryTileBitmask, elementCounter);
elementCounter = mReadBuffer.skipWays(queryParameters.queryTileBitmask,
elementCounter);
if (elementCounter == 0)
return true;
@ -890,7 +904,8 @@ public class MapDatabase implements IMapDatabase {
return false;
// wayDataContainer.textPos = textPos;
mapDatabaseCallback.renderWay(layer, tags, mWayNodes, wayLengths, changed);
mapDatabaseCallback
.renderWay(layer, tags, mWayNodes, wayLengths, changed);
}
}
@ -929,14 +944,18 @@ public class MapDatabase implements IMapDatabase {
cumulatedNumberOfPois += mReadBuffer.readUnsignedInt();
cumulatedNumberOfWays += mReadBuffer.readUnsignedInt();
if (cumulatedNumberOfPois < 0 || cumulatedNumberOfPois > MAXIMUM_ZOOM_TABLE_OBJECTS) {
LOG.warning("invalid cumulated number of POIs in row " + row + ' ' + cumulatedNumberOfPois);
if (cumulatedNumberOfPois < 0
|| cumulatedNumberOfPois > MAXIMUM_ZOOM_TABLE_OBJECTS) {
LOG.warning("invalid cumulated number of POIs in row " + row + ' '
+ cumulatedNumberOfPois);
if (mDebugFile) {
LOG.warning(DEBUG_SIGNATURE_BLOCK + mSignatureBlock);
}
return null;
} else if (cumulatedNumberOfWays < 0 || cumulatedNumberOfWays > MAXIMUM_ZOOM_TABLE_OBJECTS) {
LOG.warning("invalid cumulated number of ways in row " + row + ' ' + cumulatedNumberOfWays);
} else if (cumulatedNumberOfWays < 0
|| cumulatedNumberOfWays > MAXIMUM_ZOOM_TABLE_OBJECTS) {
LOG.warning("invalid cumulated number of ways in row " + row + ' '
+ cumulatedNumberOfWays);
if (mMapFileHeader.getMapFileInfo().debugFile) {
LOG.warning(DEBUG_SIGNATURE_BLOCK + mSignatureBlock);
}