started work on labeling

This commit is contained in:
Hannes Janetzek 2012-08-17 04:38:16 +02:00
parent 331aa6bf68
commit 7f573f0ac4
39 changed files with 2839 additions and 907 deletions

View File

@ -88,7 +88,8 @@
<string name="preferences_show_scale_bar_desc">Show the scale of the map</string>
<string name="preferences_show_tile_coordinates">Tile coordinates</string>
<string name="preferences_show_tile_coordinates_desc">Show coordinates on tiles</string>
<string name="preferences_show_tile_frames">Tile boundaries</string>
<string name="preferences_show_unmatched_ways">Draw unmatched ways</string>
<string name="preferences_show_tile_frames">Tile boundaries</string>
<string name="preferences_show_tile_frames_desc">Draw tile boundaries</string>
<string name="preferences_disable_polygons">Disable Polygon rendering</string>
<string name="preferences_show_water_tiles_desc">Highlight tiles which have the water flag set</string>

View File

@ -32,8 +32,8 @@
android:key="showFpsCounter" /> -->
<CheckBoxPreference android:title="@string/preferences_show_tile_frames" android:summary="@string/preferences_show_tile_frames_desc"
android:key="drawTileFrames" />
<!-- <CheckBoxPreference android:title="@string/preferences_show_tile_coordinates" android:summary="@string/preferences_show_tile_coordinates_desc"
android:key="drawTileCoordinates" /> -->
<CheckBoxPreference android:title="@string/preferences_show_unmatched_ways" android:summary="@string/preferences_show_unmatched_ways"
android:key="drawUnmatchedWays" />
<CheckBoxPreference android:title="@string/preferences_disable_polygons" android:summary="@string/preferences_disable_polygons"
android:key="disablePolygons" />
</PreferenceCategory>

View File

@ -29,13 +29,13 @@ public class DebugSettings {
*/
public final boolean mDrawTileFrames;
public final boolean mDrawUnmatchted;
/**
* True if highlighting of water tiles is enabled, false otherwise.
*/
public final boolean mDisablePolygons;
private final int mHashCodeValue;
/**
* @param drawTileCoordinates
* if drawing of tile coordinates is enabled.
@ -43,49 +43,14 @@ public class DebugSettings {
* if drawing of tile frames is enabled.
* @param disablePolygons
* if highlighting of water tiles is enabled.
* @param drawUnmatched
* ...
*/
public DebugSettings(boolean drawTileCoordinates, boolean drawTileFrames,
boolean disablePolygons) {
boolean disablePolygons, boolean drawUnmatched) {
mDrawTileCoordinates = drawTileCoordinates;
mDrawTileFrames = drawTileFrames;
mDrawUnmatchted = drawUnmatched;
mDisablePolygons = disablePolygons;
mHashCodeValue = calculateHashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof DebugSettings)) {
return false;
}
DebugSettings other = (DebugSettings) obj;
if (mDrawTileCoordinates != other.mDrawTileCoordinates) {
return false;
}
if (mDrawTileFrames != other.mDrawTileFrames) {
return false;
}
if (mDisablePolygons != other.mDisablePolygons) {
return false;
}
return true;
}
@Override
public int hashCode() {
return mHashCodeValue;
}
/**
* @return the hash code of this object.
*/
private int calculateHashCode() {
int result = 1;
result = 31 * result + (mDrawTileCoordinates ? 1231 : 1237);
result = 31 * result + (mDrawTileFrames ? 1231 : 1237);
result = 31 * result + (mDisablePolygons ? 1231 : 1237);
return result;
}
}

View File

@ -40,6 +40,7 @@ import org.mapsforge.android.rendertheme.RenderThemeHandler;
import org.mapsforge.android.utils.GlConfigChooser;
import org.mapsforge.core.GeoPoint;
import org.mapsforge.core.MapPosition;
import org.mapsforge.core.Tile;
import org.mapsforge.database.FileOpenResult;
import org.mapsforge.database.IMapDatabase;
import org.mapsforge.database.MapFileInfo;
@ -93,9 +94,9 @@ public class MapView extends GLSurfaceView {
private IMapRenderer mMapRenderer;
private JobQueue mJobQueue;
private MapWorker mMapWorkers[];
private int mNumMapWorkers = 4;
private int mNumMapWorkers = 6;
private JobParameters mJobParameters;
private DebugSettings mDebugSettings;
public DebugSettings debugSettings;
private String mMapFile;
/**
@ -122,6 +123,8 @@ public class MapView extends GLSurfaceView {
MapDatabaseFactory.getMapDatabase(attributeSet));
}
private boolean mDebugDatabase = false;
private MapView(Context context, AttributeSet attributeSet,
MapRenderers mapGeneratorType, MapDatabases mapDatabaseType) {
@ -131,13 +134,17 @@ public class MapView extends GLSurfaceView {
throw new IllegalArgumentException(
"context is not an instance of MapActivity");
}
Log.d(TAG, "create MapView: " + mapDatabaseType.name());
setWillNotDraw(true);
setWillNotCacheDrawing(true);
// TODO make this dpi dependent
Tile.TILE_SIZE = 400;
// setWillNotDraw(true);
// setWillNotCacheDrawing(true);
MapActivity mapActivity = (MapActivity) context;
mDebugSettings = new DebugSettings(false, false, false);
debugSettings = new DebugSettings(false, false, false, false);
mJobParameters = new JobParameters(DEFAULT_RENDER_THEME, DEFAULT_TEXT_SCALE);
mMapController = new MapController(this);
@ -161,8 +168,14 @@ public class MapView extends GLSurfaceView {
mMapWorkers = new MapWorker[mNumMapWorkers];
for (int i = 0; i < mNumMapWorkers; i++) {
IMapDatabase mapDatabase = MapDatabaseFactory
.createMapDatabase(mapDatabaseType);
IMapDatabase mapDatabase;
if (mDebugDatabase) {
mapDatabase = MapDatabaseFactory
.createMapDatabase(MapDatabases.JSON_READER);
} else {
mapDatabase = MapDatabaseFactory.createMapDatabase(mapDatabaseType);
}
IMapGenerator mapGenerator = mMapRenderer.createMapGenerator();
mapGenerator.setMapDatabase(mapDatabase);
@ -170,8 +183,6 @@ public class MapView extends GLSurfaceView {
if (i == 0) {
mMapDatabase = mapDatabase;
initMapStartPosition();
// mapGenerator.setRendertheme(DEFAULT_RENDER_THEME);
}
mMapWorkers[i] = new MapWorker(i, this, mapGenerator, mMapRenderer);
mMapWorkers[i].start();
@ -179,13 +190,13 @@ public class MapView extends GLSurfaceView {
setRenderTheme(InternalRenderTheme.OSMARENDER);
mapActivity.registerMapView(this);
setEGLConfigChooser(new GlConfigChooser());
setEGLContextClientVersion(2);
setRenderer(mMapRenderer);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
mapActivity.registerMapView(this);
}
private void initMapStartPosition() {
@ -212,7 +223,7 @@ public class MapView extends GLSurfaceView {
* @return the debug settings which are used in this MapView.
*/
public DebugSettings getDebugSettings() {
return mDebugSettings;
return debugSettings;
}
/**
@ -302,14 +313,14 @@ public class MapView extends GLSurfaceView {
* Calculates all necessary tiles and adds jobs accordingly.
*/
public void redrawTiles() {
if (getWidth() > 0 && getHeight() > 0)
if (getWidth() <= 0 || getHeight() <= 0)
return;
mMapRenderer.redrawTiles(false);
}
void clearAndRedrawMapView() {
if (getWidth() > 0 && getHeight() > 0)
private void clearAndRedrawMapView() {
if (getWidth() <= 0 || getHeight() <= 0)
return;
mMapRenderer.redrawTiles(true);
@ -343,7 +354,7 @@ public class MapView extends GLSurfaceView {
* the new DebugSettings for this MapView.
*/
public void setDebugSettings(DebugSettings debugSettings) {
mDebugSettings = debugSettings;
this.debugSettings = debugSettings;
clearAndRedrawMapView();
}
@ -377,7 +388,7 @@ public class MapView extends GLSurfaceView {
mJobQueue.clear();
mapWorkersPause();
mapWorkersPause(true);
for (MapWorker mapWorker : mMapWorkers) {
@ -445,6 +456,9 @@ public class MapView extends GLSurfaceView {
*/
public void setMapDatabase(MapDatabases mapDatabaseType) {
if (mDebugDatabase)
return;
IMapGenerator mapGenerator;
Log.d(TAG, "setMapDatabase " + mapDatabaseType.name());
@ -452,7 +466,9 @@ public class MapView extends GLSurfaceView {
if (mMapDatabaseType == mapDatabaseType)
return;
mapWorkersPause();
mMapDatabaseType = mapDatabaseType;
mapWorkersPause(true);
for (MapWorker mapWorker : mMapWorkers) {
mapGenerator = mapWorker.getMapGenerator();
@ -468,6 +484,8 @@ public class MapView extends GLSurfaceView {
setMapFile(mapFile);
mapWorkersProceed();
Log.d(TAG, ">>>");
}
/**
@ -510,7 +528,7 @@ public class MapView extends GLSurfaceView {
private boolean setRenderTheme(Theme theme) {
mapWorkersPause();
mapWorkersPause(true);
InputStream inputStream = null;
try {
@ -607,7 +625,7 @@ public class MapView extends GLSurfaceView {
int oldHeight) {
mJobQueue.clear();
mapWorkersPause();
mapWorkersPause(true);
super.onSizeChanged(width, height, oldWidth, oldHeight);
@ -668,8 +686,7 @@ public class MapView extends GLSurfaceView {
@Override
public void onPause() {
super.onPause();
for (MapWorker mapWorker : mMapWorkers)
mapWorker.pause();
mapWorkersPause(false);
// mMapMover.pause();
// mZoomAnimator.pause();
@ -678,8 +695,7 @@ public class MapView extends GLSurfaceView {
@Override
public void onResume() {
super.onResume();
for (MapWorker mapWorker : mMapWorkers)
mapWorker.proceed();
mapWorkersProceed();
// mMapMover.proceed();
// mZoomAnimator.proceed();
@ -747,21 +763,24 @@ public class MapView extends GLSurfaceView {
public void addJobs(ArrayList<MapGeneratorJob> jobs) {
mJobQueue.setJobs(jobs);
for (MapWorker m : mMapWorkers) {
for (int i = 0; i < mNumMapWorkers; i++) {
MapWorker m = mMapWorkers[i];
synchronized (m) {
m.notify();
}
}
}
private void mapWorkersPause() {
private void mapWorkersPause(boolean wait) {
for (MapWorker mapWorker : mMapWorkers) {
if (!mapWorker.isPausing())
mapWorker.pause();
}
for (MapWorker mapWorker : mMapWorkers) {
if (!mapWorker.isPausing())
mapWorker.awaitPausing();
if (wait) {
for (MapWorker mapWorker : mMapWorkers) {
if (!mapWorker.isPausing())
mapWorker.awaitPausing();
}
}
}

View File

@ -14,6 +14,8 @@
*/
package org.mapsforge.android.glrenderer;
import java.util.ArrayList;
import org.mapsforge.android.mapgenerator.MapTile;
import org.mapsforge.core.Tile;
@ -21,10 +23,12 @@ class GLMapTile extends MapTile {
VertexBufferObject lineVBO;
VertexBufferObject polygonVBO;
TextTexture texture;
LineLayers lineLayers;
PolygonLayers polygonLayers;
// MeshLayers meshLayers;
LineLayer lineLayers;
PolygonLayer polygonLayers;
ArrayList<TextItem> labels;
boolean newData;
boolean loading;

View File

@ -14,35 +14,27 @@
*/
package org.mapsforge.android.glrenderer;
import java.util.LinkedList;
class Layer {
LinkedList<PoolItem> pool;
PoolItem pool;
protected PoolItem curItem;
int verticesCnt;
int offset;
final int layer;
// final int color;
final float[] colors;
Layer(int l, int color) {
Layer(int l) {
layer = l;
verticesCnt = 0;
colors = new float[4];
colors[0] = (color >> 16 & 0xff) / 255.0f;
colors[1] = (color >> 8 & 0xff) / 255.0f;
colors[2] = (color >> 0 & 0xff) / 255.0f;
colors[3] = (color >> 24 & 0xff) / 255.0f;
}
float[] getNextPoolItem() {
curItem.used = PoolItem.SIZE;
curItem = LayerPool.get();
pool.add(curItem);
curItem.next = VertexPool.get();
curItem = curItem.next;
return curItem.vertices;
}
}

View File

@ -14,34 +14,39 @@
*/
package org.mapsforge.android.glrenderer;
import java.util.ArrayList;
import java.util.LinkedList;
import org.mapsforge.android.rendertheme.renderinstruction.Line;
import org.mapsforge.core.Tile;
import android.util.FloatMath;
class LineLayer extends Layer {
ArrayList<LineLayer> outlines;
boolean isOutline;
boolean isFixed;
Line line;
LineLayer next;
LineLayer outlines;
float width;
boolean isOutline;
LineLayer(int layer, int color, boolean outline, boolean fixed) {
super(layer, color);
isOutline = outline;
isFixed = fixed;
if (outline) {
outlines = new ArrayList<LineLayer>();
} else {
curItem = LayerPool.get();
LineLayer(int layer, Line line, boolean outline) {
super(layer);
pool = new LinkedList<PoolItem>();
pool.add(curItem);
this.line = line;
this.isOutline = outline;
if (!outline) {
curItem = VertexPool.get();
pool = curItem;
}
}
void addOutline(LineLayer link) {
if (!outlines.contains(link))
outlines.add(link);
for (LineLayer l = outlines; l != null; l = l.outlines)
if (link == l)
return;
link.outlines = outlines;
outlines = link;
}
/*
@ -49,7 +54,7 @@ class LineLayer extends Layer {
*/
void addLine(float[] pointArray, int pos, int length, float w, boolean capRound) {
float x, y, nextX, nextY, prevX, prevY, ux, uy, vx, vy, wx, wy;
double a;
float a;
int pointPos = pos;
boolean rounded = capRound;
width = w;
@ -59,10 +64,12 @@ class LineLayer extends Layer {
// amount of vertices used
verticesCnt += length + (rounded ? 6 : 2);
int MAX = PoolItem.SIZE;
float[] curVertices = curItem.vertices;
int vertexPos = curItem.used;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -77,7 +84,7 @@ class LineLayer extends Layer {
vx = nextX - x;
vy = nextY - y;
a = Math.sqrt(vx * vx + vy * vy);
a = FloatMath.sqrt(vx * vx + vy * vy);
vx = (float) (vx / a);
vy = (float) (vy / a);
@ -103,7 +110,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 1.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -113,7 +120,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 1.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -123,7 +130,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 1.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -134,7 +141,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -161,7 +168,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -171,7 +178,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -195,14 +202,14 @@ class LineLayer extends Layer {
// Unit vector pointing back to previous node
vx = prevX - x;
vy = prevY - y;
a = Math.sqrt(vx * vx + vy * vy);
a = FloatMath.sqrt(vx * vx + vy * vy);
vx = (float) (vx / a);
vy = (float) (vy / a);
// Unit vector pointing forward to next node
wx = nextX - x;
wy = nextY - y;
a = Math.sqrt(wx * wx + wy * wy);
a = FloatMath.sqrt(wx * wx + wy * wy);
wx = (float) (wx / a);
wy = (float) (wy / a);
@ -242,7 +249,7 @@ class LineLayer extends Layer {
uxw = ux * w;
uyw = uy * w;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -252,7 +259,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -271,7 +278,7 @@ class LineLayer extends Layer {
vx = prevX - x;
vy = prevY - y;
a = Math.sqrt(vx * vx + vy * vy);
a = FloatMath.sqrt(vx * vx + vy * vy);
vx = (float) (vx / a);
vy = (float) (vy / a);
@ -288,11 +295,16 @@ class LineLayer extends Layer {
outside = (x <= 0 || x >= Tile.TILE_SIZE || y <= 0 || y >= Tile.TILE_SIZE)
&& (x - vxw <= 0 || x - vxw >= Tile.TILE_SIZE || y - vyw <= 0 || y - vyw >= Tile.TILE_SIZE);
if (vertexPos == PoolItem.SIZE) {
curItem.used = vertexPos;
curItem = LayerPool.get();
pool.add(curItem);
curVertices = curItem.vertices;
// if (vertexPos == MAX) {
// curItem.used = vertexPos;
// curItem = LayerPool.get();
// pool.add(curItem);
// curVertices = curItem.vertices;
// vertexPos = 0;
// }
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -302,7 +314,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -312,7 +324,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 0.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -323,7 +335,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = -1.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -334,7 +346,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = -1.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -358,7 +370,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@ -369,7 +381,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 0.0f;
if (vertexPos == PoolItem.SIZE) {
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}

View File

@ -19,42 +19,17 @@ import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import android.util.SparseArray;
class LineLayers {
private static int NUM_VERTEX_FLOATS = 4;
private SparseArray<LineLayer> layers;
LineLayer[] array = null;
int size = 0;
LineLayers() {
layers = new SparseArray<LineLayer>(10);
}
LineLayer getLayer(int layer, int color, boolean outline, boolean fixed) {
LineLayer l = layers.get(layer);
if (l != null) {
return l;
}
l = new LineLayer(layer, color, outline, fixed);
layers.put(layer, l);
return l;
}
FloatBuffer compileLayerData(FloatBuffer buf) {
static FloatBuffer compileLayerData(LineLayer layers, FloatBuffer buf) {
FloatBuffer fbuf = buf;
int size = 0;
array = new LineLayer[layers.size()];
for (LineLayer l = layers; l != null; l = l.next)
size += l.verticesCnt;
for (int i = 0, n = layers.size(); i < n; i++) {
LineLayer l = layers.valueAt(i);
array[i] = l;
size += l.verticesCnt * NUM_VERTEX_FLOATS;
}
size *= NUM_VERTEX_FLOATS;
if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order(
@ -65,40 +40,42 @@ class LineLayers {
}
int pos = 0;
for (int i = 0, n = array.length; i < n; i++) {
LineLayer l = array[i];
PoolItem last = null, items = null;
for (LineLayer l = layers; l != null; l = l.next) {
if (l.isOutline)
continue;
for (PoolItem item : l.pool) {
for (PoolItem item = l.pool; item != null; item = item.next) {
fbuf.put(item.vertices, 0, item.used);
last = item;
}
l.offset = pos;
pos += l.verticesCnt;
LayerPool.add(l.pool);
if (last != null) {
last.next = items;
items = l.pool;
}
l.pool = null;
}
fbuf.flip();
VertexPool.add(items);
// not needed for drawing
layers = null;
fbuf.flip();
return fbuf;
}
ShortBuffer compileLayerData(ShortBuffer buf) {
static ShortBuffer compileLayerData(LineLayer layers, ShortBuffer buf) {
int size = 0;
ShortBuffer sbuf = buf;
array = new LineLayer[layers.size()];
for (LineLayer l = layers; l != null; l = l.next)
size += l.verticesCnt;
for (int i = 0, n = layers.size(); i < n; i++) {
LineLayer l = layers.valueAt(i);
array[i] = l;
size += l.verticesCnt * NUM_VERTEX_FLOATS;
}
size *= NUM_VERTEX_FLOATS;
if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 2).order(
@ -111,29 +88,40 @@ class LineLayers {
short[] data = new short[PoolItem.SIZE];
for (int i = 0, n = array.length; i < n; i++) {
LineLayer l = array[i];
PoolItem last = null, items = null;
for (LineLayer l = layers; l != null; l = l.next) {
if (l.isOutline)
continue;
for (int k = 0, m = l.pool.size(); k < m; k++) {
PoolItem item = l.pool.get(k);
for (PoolItem item = l.pool; item != null; item = item.next) {
PoolItem.toHalfFloat(item, data);
sbuf.put(data, 0, item.used);
last = item;
}
l.offset = pos;
pos += l.verticesCnt;
LayerPool.add(l.pool);
if (last != null) {
last.next = items;
items = l.pool;
}
l.pool = null;
}
sbuf.flip();
VertexPool.add(items);
// not needed for drawing
layers = null;
sbuf.flip();
return sbuf;
}
static void clear(LineLayer layer) {
for (LineLayer l = layer; l != null; l = l.next) {
if (l.pool != null)
VertexPool.add(l.pool);
}
}
}

View File

@ -14,11 +14,14 @@
*/
package org.mapsforge.android.glrenderer;
import java.util.ArrayList;
import org.mapsforge.android.mapgenerator.IMapGenerator;
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.rendertheme.IRenderCallback;
import org.mapsforge.android.rendertheme.RenderTheme;
import org.mapsforge.android.rendertheme.renderinstruction.Area;
import org.mapsforge.android.rendertheme.renderinstruction.Caption;
import org.mapsforge.android.rendertheme.renderinstruction.Line;
import org.mapsforge.android.rendertheme.renderinstruction.RenderInstruction;
import org.mapsforge.core.MercatorProjection;
@ -27,9 +30,9 @@ import org.mapsforge.core.Tile;
import org.mapsforge.core.WebMercator;
import org.mapsforge.database.IMapDatabase;
import org.mapsforge.database.IMapDatabaseCallback;
import org.mapsforge.database.QueryResult;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
@ -54,11 +57,14 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
private GLMapTile mCurrentTile;
private float[] mWayNodes;
private int[] mWays;
private short[] mWays;
private LineLayers mLineLayers;
private PolygonLayers mPolyLayers;
// private MeshLayers mMeshLayers;
private LineLayer mLineLayers;
private PolygonLayer mPolyLayers;
private LineLayer mCurLineLayer;
private PolygonLayer mCurPolyLayer;
private ArrayList<TextItem> mLabels;
private int mDrawingLayer;
private int mLevels;
@ -71,13 +77,60 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
*/
public MapGenerator() {
Log.d(TAG, "init DatabaseRenderer");
LayerPool.init();
VertexPool.init();
}
private float mPoiX = 256;
private float mPoiY = 256;
private Tag mTagEmptyName = new Tag("name", "");
private Tag mTagName;
private void filterTags(Tag[] tags) {
for (int i = 0; i < tags.length; i++) {
// Log.d(TAG, "check tag: " + tags[i]);
if (tags[i].key == mTagEmptyName.key && tags[i].value != null) {
mTagName = tags[i];
tags[i] = mTagEmptyName;
}
}
}
@Override
public void renderPointOfInterest(byte layer, int latitude, int longitude, Tag[] tags) {
// TODO Auto-generated method stub
public void renderPointOfInterest(byte layer, float latitude, float longitude,
Tag[] tags) {
mTagName = null;
long x = mCurrentTile.x;
long y = mCurrentTile.y;
long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel;
double divx, divy;
long dx = (x - (z >> 1));
long dy = (y - (z >> 1));
if (useSphericalMercator) {
divx = f900913 / (z >> 1);
divy = f900913 / (z >> 1);
mPoiX = (float) (longitude / divx - dx);
mPoiY = (float) (latitude / divy + dy);
} else {
divx = 180000000.0 / (z >> 1);
divy = z / PIx4;
mPoiX = (float) (longitude / divx - dx);
double sinLat = Math.sin(latitude * PI180);
mPoiY = (float) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
if (mPoiX < -10 || mPoiX > Tile.TILE_SIZE + 10 || mPoiY < -10
|| mPoiY > Tile.TILE_SIZE + 10)
return;
}
// remove tags that should not be cached in Rendertheme
filterTags(tags);
// Log.d(TAG, "renderPointOfInterest: " + mTagName);
MapGenerator.renderTheme.matchNode(this, tags, mCurrentTile.zoomLevel);
}
@Override
@ -94,7 +147,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
if (mProjected)
return mProjectedResult;
float minx = Float.MAX_VALUE, miny = Float.MAX_VALUE, maxx = Float.MIN_VALUE, maxy = Float.MIN_VALUE;
// float minx = Float.MAX_VALUE, miny = Float.MAX_VALUE, maxx = Float.MIN_VALUE, maxy = Float.MIN_VALUE;
float[] coords = mWayNodes;
@ -133,16 +186,16 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
lat = (float) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
}
if (area && i == 0) {
if (lon < minx)
minx = lon;
if (lon > maxx)
maxx = lon;
if (lat < miny)
miny = lat;
if (lat > maxy)
maxy = lat;
}
// if (area && i == 0) {
// if (lon < minx)
// minx = lon;
// if (lon > maxx)
// maxx = lon;
// if (lat < miny)
// miny = lat;
// if (lat > maxy)
// maxy = lat;
// }
if (cnt != 0) {
// drop small distance intermediate nodes
@ -161,38 +214,44 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
cnt += 2;
}
if (area) {
// Log.d(TAG, "area:" + (maxx - minx) * (maxy - miny));
if ((maxx - minx) * (maxy - miny) < 2000 / mCurrentTile.zoomLevel) {
mProjected = true;
mProjectedResult = false;
return false;
}
}
// if (area) {
// // Log.d(TAG, "area:" + (maxx - minx) * (maxy - miny));
// if ((maxx - minx) * (maxy - miny) < 2000 / mCurrentTile.zoomLevel) {
// mProjected = true;
// mProjectedResult = false;
// return false;
// }
// }
mWays[i] = cnt;
mWays[i] = (short) cnt;
}
mProjected = true;
mProjectedResult = true;
return true;
}
private boolean firstMatch;
private boolean prevClosed;
// private boolean firstMatch;
// private boolean prevClosed;
private RenderInstruction[] mRenderInstructions = null;
private final String TAG_WATER = "water".intern();
@Override
public void renderWay(byte layer, Tag[] tags, float[] wayNodes, int[] wayLength,
public void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLength,
boolean changed) {
// Log.d(TAG, "render way: " + layer);
mTagName = null;
mProjected = false;
mDrawingLayer = getValidLayer(layer) * mLevels;
int len = wayLength[0];
boolean closed = (wayNodes[0] == wayNodes[len - 2] &&
wayNodes[1] == wayNodes[len - 1]);
// int len = wayLength[0];
// boolean closed = (wayNodes[0] == wayNodes[len - 2] &&
// wayNodes[1] == wayNodes[len - 1]);
boolean closed = changed;
mSimplify = 0.5f;
if (closed) {
@ -201,36 +260,76 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
else
mSimplify = 0.2f;
if (tags.length == 1 && "water".equals(tags[0].value))
if (tags.length == 1 && TAG_WATER == (tags[0].value))
mSimplify = 0;
}
mWayNodes = wayNodes;
mWays = wayLength;
if (!firstMatch && prevClosed == closed && !changed) {
if (mRenderInstructions != null) {
for (int i = 0, n = mRenderInstructions.length; i < n; i++)
mRenderInstructions[i].renderWay(this, tags);
}
// MapGenerator.renderTheme.matchWay(this, tags,
// (byte) (mCurrentTile.zoomLevel + 0),
// closed, false);
// if (mRenderInstructions != null) {
// for (int i = 0, n = mRenderInstructions.length; i < n; i++)
// mRenderInstructions[i].renderWay(this, tags);
// }
// prevClosed = closed;
mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags,
(byte) (mCurrentTile.zoomLevel + 0),
closed, true);
if (mRenderInstructions == null && mDebugDrawUnmatched)
debugUnmatched(closed, tags);
// firstMatch = false;
}
private void debugUnmatched(boolean closed, Tag[] tags) {
Log.d(TAG, "way not matched: " + tags[0] + " "
+ (tags.length > 1 ? tags[1] : "") + " " + closed);
mTagName = new Tag("name", tags[0].key + ":" + tags[0].value, false);
if (closed) {
mRenderInstructions = MapGenerator.renderTheme.matchWay(this, debugTagArea,
(byte) 0, true, true);
} else {
prevClosed = closed;
mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags,
(byte) (mCurrentTile.zoomLevel + 0),
closed, true);
mRenderInstructions = MapGenerator.renderTheme.matchWay(this, debugTagWay,
(byte) 0, true, true);
}
firstMatch = false;
}
@Override
public void renderAreaCaption(String caption, float verticalOffset, Paint paint,
Paint stroke) {
// TODO Auto-generated method stub
public void renderAreaCaption(Caption caption) {
// Log.d(TAG, "renderAreaCaption: " + mTagName);
if (mTagName == null)
return;
if (caption.textKey == mTagEmptyName.key) {
if (mLabels == null)
mLabels = new ArrayList<TextItem>();
mLabels.add(new TextItem(mWayNodes[0], mWayNodes[1], mTagName.value, caption));
}
// if (caption.textKey == mTagEmptyName.key)
// mLabels.add(new TextItem(mPoiX, mPoiY, mTagName.value, caption));
}
@Override
public void renderPointOfInterestCaption(Caption caption) {
// Log.d(TAG, "renderPointOfInterestCaption: " + mPoiX + " " + mPoiY + " "
// + mTagName);
if (mTagName == null)
return;
if (caption.textKey == mTagEmptyName.key) {
if (mLabels == null)
mLabels = new ArrayList<TextItem>();
mLabels.add(new TextItem(mPoiX, mPoiY, mTagName.value, caption));
}
}
@Override
@ -239,13 +338,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
}
@Override
public void renderPointOfInterestCaption(String caption, float verticalOffset,
Paint paint, Paint stroke) {
// TODO Auto-generated method stub
}
@Override
public void renderPointOfInterestCircle(float radius, Paint fill, int level) {
// TODO Auto-generated method stub
@ -260,12 +352,60 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
@Override
public void renderWay(Line line) {
projectToTile(false);
LineLayer outlineLayer = null;
LineLayer l = mLineLayers.getLayer(mDrawingLayer + line.level, line.color, false,
line.fixed);
LineLayer lineLayer = null;
int numLayer = mDrawingLayer + line.level;
// LineLayer l = mLineLayers;
//
// for (; l != null; l = l.next)
// if (l.next == null || l.next.layer > numLayer)
// break;
//
// if (l == null || l == mLineLayers) {
// // insert at start
// lineLayer = new LineLayer(numLayer, line, false);
// lineLayer.next = mLineLayers;
// mLineLayers = lineLayer;
// } else if (l.layer == numLayer) {
// lineLayer = l;
// } else {
// // insert between current and next layer
// lineLayer = new LineLayer(numLayer, line, false);
// lineLayer.next = l.next;
// l.next = lineLayer;
// }
// FIXME simplify this...
if (mCurLineLayer != null && mCurLineLayer.layer == numLayer) {
lineLayer = mCurLineLayer;
} else if (mLineLayers == null || mLineLayers.layer > numLayer) {
// insert new layer at start
lineLayer = new LineLayer(numLayer, line, false);
lineLayer.next = mLineLayers;
mLineLayers = lineLayer;
} else {
for (LineLayer l = mLineLayers; l != null; l = l.next) {
if (l.layer == numLayer) {
lineLayer = l;
break;
}
if (l.next == null || l.next.layer > numLayer) {
lineLayer = new LineLayer(numLayer, line, false);
// insert new layer between current and next layer
lineLayer.next = l.next;
l.next = lineLayer;
}
}
}
if (lineLayer == null)
return;
mCurLineLayer = lineLayer;
float w = line.strokeWidth;
@ -273,13 +413,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
w *= mStrokeScale;
w *= mProjectionScaleFactor;
}
if (line.outline != -1) {
Line outline = MapGenerator.renderTheme.getOutline(line.outline);
if (outline != null) {
outlineLayer = mLineLayers.getLayer(mDrawingLayer + outline.level,
outline.color, true, false);
outlineLayer.addOutline(l);
}
else {
w *= 1.2; // TODO make this dependent on dpi
}
for (int i = 0, pos = 0, n = mWays.length; i < n; i++) {
@ -287,10 +422,44 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
// need at least two points
if (length >= 4)
l.addLine(mWayNodes, pos, length, w, line.round);
lineLayer.addLine(mWayNodes, pos, length, w, line.round);
pos += length;
}
if (line.outline < 0)
return;
Line outline = MapGenerator.renderTheme.getOutline(line.outline);
if (outline == null)
return;
numLayer = mDrawingLayer + outline.level;
if (mLineLayers == null || mLineLayers.layer > numLayer) {
// insert new layer at start
outlineLayer = new LineLayer(numLayer, outline, true);
outlineLayer.next = mLineLayers;
mLineLayers = outlineLayer;
} else {
for (LineLayer l = mLineLayers; l != null; l = l.next) {
if (l.layer == numLayer) {
outlineLayer = l;
break;
}
if (l.next == null || l.next.layer > numLayer) {
outlineLayer = new LineLayer(numLayer, outline, true);
// insert new layer between current and next layer
outlineLayer.next = l.next;
l.next = outlineLayer;
}
}
}
if (outlineLayer != null)
outlineLayer.addOutline(lineLayer);
}
@Override
@ -302,17 +471,41 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
if (!projectToTile(false))
return;
PolygonLayer l = mPolyLayers.getLayer(mDrawingLayer + area.level, area.color,
area.fade);
int numLayer = mDrawingLayer + area.level;
PolygonLayer layer = null;
// MeshLayer l = mMeshLayers.getLayer(mDrawingLayer + area.level, area.color,
// area.fade);
if (mCurPolyLayer != null && mCurPolyLayer.layer == numLayer) {
layer = mCurPolyLayer;
} else if (mPolyLayers == null || mPolyLayers.layer > numLayer) {
// insert new layer at start
layer = new PolygonLayer(numLayer, area);
layer.next = mPolyLayers;
mPolyLayers = layer;
} else {
for (PolygonLayer l = mPolyLayers; l != null; l = l.next) {
if (l.layer >= numLayer) {
layer = l;
break;
}
if (l.next == null || l.next.layer > numLayer) {
layer = new PolygonLayer(numLayer, area);
// insert new layer between current and next layer
layer.next = l.next;
l.next = layer;
}
}
}
if (layer == null)
return;
mCurPolyLayer = layer;
for (int i = 0, pos = 0, n = mWays.length; i < n; i++) {
int length = mWays[i];
// need at least three points
if (length >= 6)
l.addPolygon(mWayNodes, pos, length);
layer.addPolygon(mWayNodes, pos, length);
pos += length;
}
@ -338,10 +531,10 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
}
private boolean mDebugDrawPolygons;
boolean mDebugDrawUnmatched;
@Override
public boolean executeJob(MapGeneratorJob mapGeneratorJob) {
// Log.d(TAG, "load " + mCurrentTile);
if (!(mapGeneratorJob.tile instanceof GLMapTile))
return false;
@ -353,7 +546,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mCurrentTile = (GLMapTile) mapGeneratorJob.tile;
mDebugDrawPolygons = !mapGeneratorJob.debugSettings.mDisablePolygons;
mDebugDrawUnmatched = mapGeneratorJob.debugSettings.mDrawUnmatchted;
if (mCurrentTile.isLoading || mCurrentTile.isDrawn)
return false;
@ -363,32 +556,49 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
setScaleStrokeWidth(mCurrentTile.zoomLevel);
mLineLayers = new LineLayers();
mPolyLayers = new PolygonLayers();
// mMeshLayers = new MeshLayers();
mCurrentTile.lineLayers = mLineLayers;
mCurrentTile.polygonLayers = mPolyLayers;
// mCurrentTile.meshLayers = mMeshLayers;
mLineLayers = null;
mPolyLayers = null;
mLabels = null;
firstMatch = true;
// firstMatch = true;
mProjectionScaleFactor = (float) (1.0 / Math.cos(MercatorProjection
.pixelYToLatitude(mCurrentTile.pixelY, mCurrentTile.zoomLevel)
* (Math.PI / 180))) / 1.5f;
mMapDatabase.executeQuery(mCurrentTile, this);
* (Math.PI / 180))); // / 1.5f;
if (mMapDatabase.executeQuery(mCurrentTile, this) != QueryResult.SUCCESS) {
LineLayers.clear(mLineLayers);
PolygonLayers.clear(mPolyLayers);
mLineLayers = null;
mPolyLayers = null;
mCurrentTile.isLoading = false;
return false;
}
if (mapGeneratorJob.debugSettings.mDrawTileFrames) {
float[] coords = { 0, 0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE,
Tile.TILE_SIZE, 0, 0, 0 };
LineLayer ll = mLineLayers.getLayer(Integer.MAX_VALUE, Color.BLACK, false,
true);
ll.addLine(coords, 0, coords.length, 1.5f, false);
mTagName = new Tag("name", mCurrentTile.toString(), false);
mPoiX = 10;
mPoiY = 10;
MapGenerator.renderTheme.matchNode(this, debugTagWay, (byte) 0);
// float[] coords = { 0, 0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE,
// Tile.TILE_SIZE, 0, 0, 0 };
// LineLayer ll = mLineLayers.getLayer(Integer.MAX_VALUE, Color.BLACK, false,
// true, -1);
// ll.addLine(coords, 0, coords.length, 1.5f, false);
}
mCurrentTile.lineLayers = mLineLayers;
mCurrentTile.polygonLayers = mPolyLayers;
mCurrentTile.labels = mLabels;
mCurPolyLayer = null;
mCurLineLayer = null;
mCurrentTile.newData = true;
return true;
}
private Tag[] debugTagWay = { new Tag("debug", "way") };
private Tag[] debugTagArea = { new Tag("debug", "area") };
private float mProjectionScaleFactor;
private static byte getValidLayer(byte layer) {
@ -431,4 +641,13 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
public void setRenderTheme(RenderTheme theme) {
MapGenerator.renderTheme = theme;
}
@Override
public boolean checkWay(Tag[] tags, boolean closed) {
mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags,
(byte) (mCurrentTile.zoomLevel + 0), closed, false);
return mRenderInstructions != null;
}
}

View File

@ -25,6 +25,7 @@ import static android.opengl.GLES20.GL_EXTENSIONS;
import static android.opengl.GLES20.GL_FLOAT;
import static android.opengl.GLES20.GL_INVERT;
import static android.opengl.GLES20.GL_NEVER;
import static android.opengl.GLES20.GL_ONE;
import static android.opengl.GLES20.GL_ONE_MINUS_SRC_ALPHA;
import static android.opengl.GLES20.GL_SCISSOR_TEST;
import static android.opengl.GLES20.GL_SRC_ALPHA;
@ -80,6 +81,7 @@ import org.mapsforge.android.mapgenerator.JobParameters;
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.mapgenerator.TileCacheKey;
import org.mapsforge.android.mapgenerator.TileDistanceSort;
import org.mapsforge.android.rendertheme.renderinstruction.Line;
import org.mapsforge.android.utils.GlConfigChooser;
import org.mapsforge.android.utils.GlUtils;
import org.mapsforge.core.MapPosition;
@ -102,7 +104,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// private boolean mTriangulate = false;
private static int CACHE_TILES_MAX = 400;
private static int CACHE_TILES_MAX = 250;
private static int CACHE_TILES = CACHE_TILES_MAX;
private static int LIMIT_BUFFERS = 20 * MB;
@ -127,28 +129,29 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private JobParameters mJobParameter;
private MapPosition mMapPosition, mPrevMapPosition;
private int mWidth, mHeight;
private float mAspect;
private static int mWidth, mHeight;
private static float mAspect;
// draw position is updated from current position in onDrawFrame
// keeping the position consistent while drawing
private double mDrawX, mDrawY, mDrawZ, mCurX, mCurY, mCurZ;
private float mDrawScale, mCurScale;
private static double mDrawX, mDrawY, mDrawZ, mCurX, mCurY, mCurZ;
private static float mDrawScale, mCurScale;
// current center tile
private long mTileX, mTileY;
private static long mTileX, mTileY;
private FloatBuffer floatBuffer[];
private ShortBuffer shortBuffer[];
private static int rotateBuffers = 2;
private static FloatBuffer floatBuffer[];
private static ShortBuffer shortBuffer[];
boolean useHalfFloat = false;
static boolean useHalfFloat = false;
// bytes currently loaded in VBOs
private int mBufferMemoryUsage;
private static int mBufferMemoryUsage;
// flag set by updateVisibleList when current visible tiles changed.
// used in onDrawFrame to nextTiles to curTiles
private boolean mUpdateTiles;
private static boolean mUpdateTiles;
class TilesData {
int cnt = 0;
@ -159,30 +162,30 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
}
private float[] mMVPMatrix = new float[16];
private static float[] mMVPMatrix = new float[16];
// private float[] mMMatrix = new float[16];
// private float[] mRMatrix = new float[16];
// newTiles is set in updateVisibleList and synchronized swapped
// with nextTiles on main thread.
// nextTiles is swapped with curTiles in onDrawFrame in GL thread.
private TilesData newTiles, nextTiles, curTiles;
private static TilesData newTiles, nextTiles, curTiles;
private boolean mInitial;
// shader handles
private int gLineProgram;
private int gLineVertexPositionHandle;
private int gLineTexturePositionHandle;
private int gLineColorHandle;
private int gLineMatrixHandle;
private int gLineModeHandle;
private int gLineWidthHandle;
private static int lineProgram;
private static int hLineVertexPosition;
private static int hLineTexturePosition;
private static int hLineColor;
private static int hLineMatrix;
private static int hLineMode;
private static int hLineWidth;
private int gPolygonProgram;
private int gPolygonVertexPositionHandle;
private int gPolygonMatrixHandle;
private int gPolygonColorHandle;
private static int polygonProgram;
private static int hPolygonVertexPosition;
private static int hPolygonMatrix;
private static int hPolygonColor;
/**
*
@ -261,7 +264,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
GLMapTile t = mTileList.remove(j);
if (t.isActive) {
// Log.d(TAG, "EEEK removing active tile");
Log.d(TAG, "EEEK removing active tile");
mTileList.add(t);
continue;
}
@ -441,18 +444,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
updateTileDistances();
// scramble tile draw order, might help to make draw calls independent... just a guess :)
// scramble tile draw order: might help to make gl
// pipelines more independent... just a guess :)
for (int i = 1; i < tiles / 2; i += 2) {
GLMapTile tmp = newTiles.tiles[i];
newTiles.tiles[i] = newTiles.tiles[tiles - i];
newTiles.tiles[tiles - i] = tmp;
}
int removes = mTiles.size() - CACHE_TILES;
if (removes > 0)
Collections.sort(mTileList, mTileDistanceSort);
// pass new tile list to glThread
synchronized (this) {
for (int i = 0; i < nextTiles.cnt; i++)
@ -472,7 +471,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mUpdateTiles = true;
}
limitCache(removes);
int removes = mTiles.size() - CACHE_TILES;
if (removes > 0) {
Collections.sort(mTileList, mTileDistanceSort);
limitCache(removes);
}
if (mJobList.size() > 0)
mMapView.addJobs(mJobList);
@ -593,7 +597,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
float alpha = 1.0f;
if (l.fadeLevel >= mDrawZ) {
if (l.area.fade >= mDrawZ) {
alpha = (mDrawScale > 1.3f ? mDrawScale : 1.3f) - alpha;
if (alpha > 1.0f)
@ -608,8 +612,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
blend = false;
}
glUniform4f(gPolygonColorHandle,
l.colors[0], l.colors[1], l.colors[2], alpha);
glUniform4f(hPolygonColor,
l.area.color[0], l.area.color[1], l.area.color[2], alpha);
// set stencil buffer mask used to draw this layer
glStencilFunc(GL_EQUAL, 0xff, 1 << c);
@ -625,7 +629,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private boolean drawPolygons(GLMapTile tile, int diff) {
int cnt = 0;
if (tile.polygonLayers == null || tile.polygonLayers.array == null)
if (tile.polygonLayers == null)
return true;
glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
@ -635,27 +639,23 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
if (useHalfFloat) {
glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
glVertexAttribPointer(hPolygonVertexPosition, 2,
OES_HALF_FLOAT, false, 0,
POLYGON_VERTICES_DATA_POS_OFFSET);
} else {
glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
glVertexAttribPointer(hPolygonVertexPosition, 2,
GL_FLOAT, false, 0,
POLYGON_VERTICES_DATA_POS_OFFSET);
}
// glBindBuffer(GL_ARRAY_BUFFER, 0);
}
setMatrix(tile, diff);
glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0);
glUniformMatrix4fv(hPolygonMatrix, 1, false, mMVPMatrix, 0);
boolean firstPass = true;
for (int i = 0, n = tile.polygonLayers.array.length; i < n; i++) {
PolygonLayer l = tile.polygonLayers.array[i];
for (PolygonLayer l = tile.polygonLayers; l != null; l = l.next) {
// fade out polygon layers (set in RederTheme)
if (l.fadeLevel > 0 && l.fadeLevel > mDrawZ)
if (l.area.fade > 0 && l.area.fade > mDrawZ)
continue;
if (cnt == 0) {
@ -668,8 +668,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (firstPass)
firstPass = false;
else {
// eeek, nexus! - cant do old-school polygons
// glFinish();
GLES20.glFlush();
// clear stencilbuffer
glStencilMask(0xFF);
@ -703,56 +702,16 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// eeek, nexus! - cant do old-school polygons
// glFinish();
}
GLES20.glFlush();
return true;
}
private int mLastBoundVBO;
// private boolean drawTriangles(GLMapTile tile, int diff) {
//
// if (tile.meshLayers == null || tile.meshLayers.array == null)
// return true;
//
// glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
//
// if (mLastBoundVBO != tile.polygonVBO.id) {
// mLastBoundVBO = tile.polygonVBO.id;
// glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
//
// if (useHalfFloat) {
// glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
// OES_HALF_FLOAT, false, 0,
// POLYGON_VERTICES_DATA_POS_OFFSET);
// } else {
// glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
// GL_FLOAT, false, 0,
// POLYGON_VERTICES_DATA_POS_OFFSET);
// }
//
// // glBindBuffer(GL_ARRAY_BUFFER, 0);
// }
// setMatrix(tile, diff);
// glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0);
//
// MeshLayer[] layers = tile.meshLayers.array;
//
// for (int i = 0, n = layers.length; i < n; i++) {
// MeshLayer l = layers[i];
// glUniform4fv(gPolygonColorHandle, 1, l.colors, 0);
//
// // glUniform4f(gPolygonColorHandle, 1, 0, 0, 1);
//
// // System.out.println("draw: " + l.offset + " " + l.verticesCnt);
// glDrawArrays(GL_TRIANGLES, l.offset, l.verticesCnt);
// }
//
// return true;
// }
private static int mLastBoundVBO;
private boolean drawLines(GLMapTile tile, int diff) {
float z = 1;
if (tile.lineLayers == null || tile.lineLayers.array == null)
if (tile.lineLayers == null)
return false;
glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
@ -762,27 +721,24 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id);
if (useHalfFloat) {
glVertexAttribPointer(gLineVertexPositionHandle, 2, OES_HALF_FLOAT,
glVertexAttribPointer(hLineVertexPosition, 2, OES_HALF_FLOAT,
false, 8, LINE_VERTICES_DATA_POS_OFFSET);
glVertexAttribPointer(gLineTexturePositionHandle, 2, OES_HALF_FLOAT,
glVertexAttribPointer(hLineTexturePosition, 2, OES_HALF_FLOAT,
false, 8, LINE_VERTICES_DATA_TEX_OFFSET >> 1);
} else {
glVertexAttribPointer(gLineVertexPositionHandle, 2, GL_FLOAT,
glVertexAttribPointer(hLineVertexPosition, 2, GL_FLOAT,
false, 16, LINE_VERTICES_DATA_POS_OFFSET);
glVertexAttribPointer(gLineTexturePositionHandle, 2, GL_FLOAT,
glVertexAttribPointer(hLineTexturePosition, 2, GL_FLOAT,
false, 16, LINE_VERTICES_DATA_TEX_OFFSET);
}
// glBindBuffer(GL_ARRAY_BUFFER, 0);
}
if (diff != 0)
z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff);
setMatrix(tile, diff);
glUniformMatrix4fv(gLineMatrixHandle, 1, false, mMVPMatrix, 0);
LineLayer[] layers = tile.lineLayers.array;
glUniformMatrix4fv(hLineMatrix, 1, false, mMVPMatrix, 0);
boolean drawOutlines = false;
boolean drawFixed = false;
@ -792,52 +748,67 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// 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];
boolean first = true;
for (LineLayer l = tile.lineLayers; l != null; l = l.next) {
Line line = l.line;
if (line.fade > 0 && line.fade > mDrawZ)
continue;
// set line width and mode
if ((i == 0) || (l.isOutline != drawOutlines) || (l.isFixed != drawFixed)) {
if (first || (l.isOutline != drawOutlines)
|| (line.fixed != drawFixed)) {
first = false;
drawOutlines = l.isOutline;
drawFixed = l.isFixed;
drawFixed = line.fixed;
if (drawOutlines) {
glUniform2f(gLineModeHandle, 0, wdiv);
glUniform2f(hLineMode, 0, wdiv);
} else if (!drawFixed) {
glUniform2f(gLineModeHandle, 0, wdiv * 0.98f);
glUniform2f(hLineMode, 0, wdiv * 0.98f);
}
}
if (drawFixed) {
if (l.width < 1.0)
glUniform2f(gLineModeHandle, 0.4f, fdiv);
glUniform2f(hLineMode, 0.4f, fdiv);
else
glUniform2f(gLineModeHandle, 0, fdiv);
glUniform2f(hLineMode, 0, fdiv);
}
if (line.fade >= mDrawZ) {
float alpha = 1.0f;
alpha = (mDrawScale > 1.3f ? mDrawScale : 1.3f) - alpha;
if (alpha > 1.0f)
alpha = 1.0f;
glUniform4f(hLineColor,
line.color[0], line.color[1], line.color[2], alpha);
} else {
glUniform4fv(hLineColor, 1, line.color, 0);
}
glUniform4fv(gLineColorHandle, 1, l.colors, 0);
if (drawOutlines) {
for (int j = 0, m = l.outlines.size(); j < m; j++) {
LineLayer o = l.outlines.get(j);
for (LineLayer o = l.outlines; o != null; o = o.outlines) {
if (mSimpleLines)
glUniform1f(gLineWidthHandle, o.width);
glUniform1f(hLineWidth, o.width);
glDrawArrays(GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
}
}
else {
if (mSimpleLines)
glUniform1f(gLineWidthHandle, l.width);
glUniform1f(hLineWidth, l.width);
glDrawArrays(GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
}
}
GLES20.glFlush();
return true;
}
private void setMatrix(GLMapTile tile, int diff) {
private static void setMatrix(GLMapTile tile, int diff) {
float x, y, scale;
float z = 1;
@ -858,7 +829,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mMVPMatrix[5] = (scale);
}
private boolean setTileScissor(GLMapTile tile, float div) {
private static boolean setTileScissor(GLMapTile tile, float div) {
double dx, dy, scale;
@ -916,12 +887,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private int uploadCnt = 0;
private boolean uploadTileData(GLMapTile tile) {
ShortBuffer sbuf = null;
FloatBuffer fbuf = null;
// double start = SystemClock.uptimeMillis();
// use multiple buffers to avoid overwriting buffer while current data is uploaded
// (or rather the blocking which is required to avoid this)
if (uploadCnt >= 10) {
// use multiple buffers to avoid overwriting buffer while current
// data is uploaded (or rather the blocking which is required to avoid this)
if (uploadCnt >= rotateBuffers) {
// mMapView.requestRender();
// return false;
uploadCnt = 0;
@ -939,27 +912,34 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
tile.polygonVBO = mVBOs.remove(mVBOs.size() - 1);
}
}
if (useHalfFloat)
shortBuffer[uploadCnt * 2] = tile.lineLayers
.compileLayerData(shortBuffer[uploadCnt * 2]);
else
floatBuffer[uploadCnt * 2] = tile.lineLayers
.compileLayerData(floatBuffer[uploadCnt * 2]);
int size = 0;
if (tile.lineLayers.size > 0) {
if (useHalfFloat) {
sbuf = LineLayers.compileLayerData(tile.lineLayers,
shortBuffer[uploadCnt * 2]);
size = sbuf.remaining();
shortBuffer[uploadCnt * 2] = sbuf;
} else {
fbuf = LineLayers.compileLayerData(tile.lineLayers,
floatBuffer[uploadCnt * 2]);
size = fbuf.remaining();
floatBuffer[uploadCnt * 2] = fbuf;
}
if (size > 0) {
mBufferMemoryUsage -= tile.lineVBO.size;
glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id);
// glBufferData(GL_ARRAY_BUFFER, 0, null, GL_DYNAMIC_DRAW);
if (useHalfFloat) {
tile.lineVBO.size = tile.lineLayers.size * SHORT_BYTES;
tile.lineVBO.size = size * SHORT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size,
shortBuffer[uploadCnt * 2], GL_DYNAMIC_DRAW);
sbuf, GL_DYNAMIC_DRAW);
} else {
tile.lineVBO.size = tile.lineLayers.size * FLOAT_BYTES;
tile.lineVBO.size = size * FLOAT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size,
floatBuffer[uploadCnt * 2], GL_DYNAMIC_DRAW);
fbuf, GL_DYNAMIC_DRAW);
}
mBufferMemoryUsage += tile.lineVBO.size;
@ -968,16 +948,19 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
tile.lineLayers = null;
}
// if (!mTriangulate) {
if (useHalfFloat)
shortBuffer[uploadCnt * 2 + 1] = tile.polygonLayers
.compileLayerData(shortBuffer[uploadCnt * 2 + 1]);
else
floatBuffer[uploadCnt * 2 + 1] = tile.polygonLayers
.compileLayerData(floatBuffer[uploadCnt * 2 + 1]);
if (useHalfFloat) {
sbuf = PolygonLayers.compileLayerData(tile.polygonLayers,
shortBuffer[uploadCnt * 2 + 1]);
size = sbuf.remaining();
shortBuffer[uploadCnt * 2 + 1] = sbuf;
} else {
fbuf = PolygonLayers.compileLayerData(tile.polygonLayers,
floatBuffer[uploadCnt * 2 + 1]);
size = fbuf.remaining();
floatBuffer[uploadCnt * 2 + 1] = fbuf;
}
// Upload polygon data to vertex buffer object
if (tile.polygonLayers.size > 0) {
if (size > 0) {
mBufferMemoryUsage -= tile.polygonVBO.size;
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
@ -985,54 +968,24 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// GL_DYNAMIC_DRAW);
if (useHalfFloat) {
tile.polygonVBO.size = tile.polygonLayers.size * SHORT_BYTES;
tile.polygonVBO.size = size * SHORT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
shortBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW);
sbuf, GL_DYNAMIC_DRAW);
} else {
tile.polygonVBO.size = tile.polygonLayers.size * FLOAT_BYTES;
tile.polygonVBO.size = size * FLOAT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
floatBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW);
fbuf, GL_DYNAMIC_DRAW);
}
mBufferMemoryUsage += tile.polygonVBO.size;
} else {
tile.polygonLayers = null;
}
// }
// else {
// if (useHalfFloat)
// shortBuffer[uploadCnt * 2 + 1] = tile.meshLayers
// .compileLayerData(shortBuffer[uploadCnt * 2 + 1]);
// else
// floatBuffer[uploadCnt * 2 + 1] = tile.meshLayers
// .compileLayerData(floatBuffer[uploadCnt * 2 + 1]);
//
// // Upload triangle data to vertex buffer object
// if (tile.meshLayers.size > 0) {
// mBufferMemoryUsage -= tile.polygonVBO.size;
//
// glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
// // glBufferData(GL_ARRAY_BUFFER, 0, null,
// // GL_DYNAMIC_DRAW);
//
// if (useHalfFloat) {
// tile.polygonVBO.size = tile.meshLayers.size * SHORT_BYTES;
// glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
// shortBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW);
// } else {
// tile.polygonVBO.size = tile.meshLayers.size * FLOAT_BYTES;
// glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
// floatBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW);
// }
// mBufferMemoryUsage += tile.polygonVBO.size;
//
// } else {
// tile.meshLayers = null;
// }
// }
tile.newData = false;
tile.isDrawn = true;
tile.isLoading = false;
// double compile = SystemClock.uptimeMillis();
// glFinish();
// double now = SystemClock.uptimeMillis();
@ -1044,8 +997,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
return true;
}
// private long startTime = SystemClock.uptimeMillis();
@Override
public void onDrawFrame(GL10 glUnused) {
long start = 0, poly_time = 0, clear_time = 0;
@ -1057,20 +1008,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
start = SystemClock.uptimeMillis();
glStencilMask(0xFF);
glDisable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// long endTime = SystemClock.uptimeMillis();
// long dt = endTime - startTime;
// if (dt < 33)
// try {
// Thread.sleep(33 - dt);
// } catch (InterruptedException e) {
// Log.d(TAG, "interrupt");
// return;
// }
// startTime = SystemClock.uptimeMillis();
synchronized (this) {
mDrawX = mCurX;
mDrawY = mCurY;
@ -1114,13 +1053,20 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
uploadCnt = 0;
mLastBoundVBO = -1;
int updateTextures = 0;
// check visible tiles, set tile clip scissors, upload new vertex data
for (int i = 0; i < tileCnt; i++) {
GLMapTile tile = tiles[i];
if (!setTileScissor(tile, 1))
continue;
if (tile.texture == null && tile.labels != null &&
mTextRenderer.drawToTexture(tile))
updateTextures++;
if (tile.newData) {
uploadTileData(tile);
continue;
@ -1143,25 +1089,25 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
}
if (GlUtils.checkGlOutOfMemory("upload: " + mBufferMemoryUsage)
&& LIMIT_BUFFERS > MB)
LIMIT_BUFFERS -= MB;
if (updateTextures > 0)
mTextRenderer.compileTextures();
// if (GlUtils.checkGlOutOfMemory("upload: " + mBufferMemoryUsage)
// && LIMIT_BUFFERS > MB)
// LIMIT_BUFFERS -= MB;
if (timing)
clear_time = (SystemClock.uptimeMillis() - start);
glEnable(GL_SCISSOR_TEST);
glUseProgram(gPolygonProgram);
glEnableVertexAttribArray(gPolygonVertexPositionHandle);
glUseProgram(polygonProgram);
glEnableVertexAttribArray(hPolygonVertexPosition);
// if (!mTriangulate) {
glDisable(GL_BLEND);
// Draw Polygons
glEnable(GL_STENCIL_TEST);
// glEnableVertexAttribArray(gPolygonVertexPositionHandle);
for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible) {
GLMapTile tile = tiles[i];
@ -1172,24 +1118,11 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
drawProxyPolygons(tile);
}
}
// GlUtils.checkGlError("polygons");
glDisable(GL_STENCIL_TEST);
// } else {
// // Draw Triangles
// for (int i = 0; i < tileCnt; i++) {
// if (tiles[i].isVisible) {
// GLMapTile tile = tiles[i];
//
// if (tile.isDrawn)
// drawTriangles(tile, 0);
// else
// drawProxyTriangles(tile);
// }
// }
// // GlUtils.checkGlError("triangles");
// }
// required on GalaxyII, Android 2.3.3 (cant just VAA enable once...)
glDisableVertexAttribArray(gPolygonVertexPositionHandle);
glDisableVertexAttribArray(hPolygonVertexPosition);
if (timing) {
glFinish();
@ -1198,10 +1131,10 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// Draw lines
glEnable(GL_BLEND);
glUseProgram(gLineProgram);
glUseProgram(lineProgram);
glEnableVertexAttribArray(gLineVertexPositionHandle);
glEnableVertexAttribArray(gLineTexturePositionHandle);
glEnableVertexAttribArray(hLineVertexPosition);
glEnableVertexAttribArray(hLineTexturePosition);
for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible) {
@ -1214,20 +1147,37 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
}
glDisableVertexAttribArray(hLineVertexPosition);
glDisableVertexAttribArray(hLineTexturePosition);
glDisable(GL_SCISSOR_TEST);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
mTextRenderer.beginDraw();
for (int i = 0; i < tileCnt; i++) {
if (!tiles[i].isVisible || tiles[i].texture == null)
continue;
setMatrix(tiles[i], 0);
mTextRenderer.drawTile(tiles[i], mMVPMatrix);
}
mTextRenderer.endDraw();
if (timing) {
glFinish();
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start) + " "
+ clear_time + " " + poly_time);
}
glDisableVertexAttribArray(gLineVertexPositionHandle);
glDisableVertexAttribArray(gLineTexturePositionHandle);
// GlUtils.checkGlError("lines");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
private int[] mVboIds;
private static TextRenderer mTextRenderer;
@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
GlUtils.checkGlError("onSurfaceChanged");
mVBOs.clear();
mTiles.clear();
mTileList.clear();
@ -1246,20 +1196,27 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mAspect = (float) height / width;
glViewport(0, 0, width, height);
GlUtils.checkGlError("glViewport");
int tiles = (mWidth / Tile.TILE_SIZE + 4) * (mHeight / Tile.TILE_SIZE + 4);
curTiles = new TilesData(tiles);
newTiles = new TilesData(tiles);
nextTiles = new TilesData(tiles);
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
* (mHeight / (Tile.TILE_SIZE / 2) + 2);
curTiles = new TilesData(numTiles);
newTiles = new TilesData(numTiles);
nextTiles = new TilesData(numTiles);
// Set up vertex buffer objects
int numVBO = (CACHE_TILES + tiles) * 2;
mVboIds = new int[numVBO];
int numVBO = (CACHE_TILES + numTiles) * 2;
int[] mVboIds = new int[numVBO];
glGenBuffers(numVBO, mVboIds, 0);
GlUtils.checkGlError("glGenBuffers");
for (int i = 0; i < numVBO; i++)
mVBOs.add(new VertexBufferObject(mVboIds[i]));
// Set up textures
mTextRenderer = new TextRenderer(numTiles * 2);
mDebugSettings = mMapView.getDebugSettings();
mJobParameter = mMapView.getJobParameters();
@ -1273,14 +1230,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Set up the program for rendering lines
gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
lineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
Shaders.gLineFragmentShader);
if (gLineProgram == 0) {
if (lineProgram == 0) {
mSimpleLines = true;
Log.e(TAG, "trying simple line program.");
gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
lineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
Shaders.gLineFragmentShaderSimple);
if (gLineProgram == 0) {
if (lineProgram == 0) {
Log.e(TAG, "Could not create line program.");
return;
}
@ -1290,48 +1247,51 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (ext.indexOf("GL_OES_vertex_half_float") >= 0) {
useHalfFloat = true;
shortBuffer = new ShortBuffer[20];
shortBuffer = new ShortBuffer[rotateBuffers * 2];
}
else {
floatBuffer = new FloatBuffer[20];
floatBuffer = new FloatBuffer[rotateBuffers * 2];
}
Log.d(TAG, "Extensions: " + ext);
gLineMatrixHandle = glGetUniformLocation(gLineProgram, "u_center");
gLineModeHandle = glGetUniformLocation(gLineProgram, "u_mode");
gLineColorHandle = glGetUniformLocation(gLineProgram, "u_color");
gLineVertexPositionHandle = GLES20
.glGetAttribLocation(gLineProgram, "a_position");
gLineTexturePositionHandle = glGetAttribLocation(gLineProgram, "a_st");
hLineMatrix = glGetUniformLocation(lineProgram, "u_center");
hLineMode = glGetUniformLocation(lineProgram, "u_mode");
hLineColor = glGetUniformLocation(lineProgram, "u_color");
hLineVertexPosition = GLES20.glGetAttribLocation(lineProgram, "a_position");
hLineTexturePosition = glGetAttribLocation(lineProgram, "a_st");
if (mSimpleLines)
gLineWidthHandle = glGetUniformLocation(gLineProgram, "u_width");
hLineWidth = glGetUniformLocation(lineProgram, "u_width");
// Set up the program for rendering polygons
gPolygonProgram = GlUtils.createProgram(Shaders.gPolygonVertexShader,
polygonProgram = GlUtils.createProgram(Shaders.gPolygonVertexShader,
Shaders.gPolygonFragmentShader);
if (gPolygonProgram == 0) {
if (polygonProgram == 0) {
Log.e(TAG, "Could not create polygon program.");
return;
}
gPolygonMatrixHandle = glGetUniformLocation(gPolygonProgram, "u_center");
gPolygonVertexPositionHandle = glGetAttribLocation(gPolygonProgram,
"a_position");
gPolygonColorHandle = glGetUniformLocation(gPolygonProgram, "u_color");
hPolygonMatrix = glGetUniformLocation(polygonProgram, "u_center");
hPolygonVertexPosition = glGetAttribLocation(polygonProgram, "a_position");
hPolygonColor = glGetUniformLocation(polygonProgram, "u_color");
// glUseProgram(gPolygonProgram);
// glEnableVertexAttribArray(gPolygonVertexPositionHandle);
// glUseProgram(polygonProgram);
// glEnableVertexAttribArray(hPolygonVertexPosition);
//
// glUseProgram(gLineProgram);
// glEnableVertexAttribArray(gLineVertexPositionHandle);
// glEnableVertexAttribArray(gLineTexturePositionHandle);
// glUseProgram(lineProgram);
// glEnableVertexAttribArray(hLineVertexPosition);
// glEnableVertexAttribArray(hLineTexturePosition);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
glDisable(GL_DITHER);
glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
glClearStencil(0);
GlUtils.checkGlError("onSurfaceCreated");
}
private void drawProxyLines(GLMapTile tile) {
@ -1397,38 +1357,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
}
// private void drawProxyTriangles(GLMapTile tile) {
// if (tile.parent != null && tile.parent.isDrawn) {
// tile.parent.sx = tile.sx;
// tile.parent.sy = tile.sy;
// tile.parent.sw = tile.sw;
// tile.parent.sh = tile.sh;
// drawTriangles(tile.parent, -1);
// } else {
// int drawn = 0;
//
// for (int i = 0; i < 4; i++) {
// GLMapTile c = tile.child[i];
//
// if (c != null && c.isDrawn && setTileScissor(c, 2)) {
// drawTriangles(c, 1);
// drawn++;
// }
// }
//
// if (drawn < 4 && tile.parent != null) {
// GLMapTile p = tile.parent.parent;
// if (p != null && p.isDrawn) {
// p.sx = tile.sx;
// p.sy = tile.sy;
// p.sw = tile.sw;
// p.sh = tile.sh;
// drawTriangles(p, -2);
// }
// }
// }
// }
@Override
public boolean processedTile() {
return true;

View File

@ -14,21 +14,21 @@
*/
package org.mapsforge.android.glrenderer;
import java.util.LinkedList;
import org.mapsforge.android.rendertheme.renderinstruction.Area;
class PolygonLayer extends Layer {
int fadeLevel;
PolygonLayer next;
Area area;
private boolean first = true;
private float originX;
private float originY;
PolygonLayer(int layer, int color, int fade) {
super(layer, color);
fadeLevel = fade;
curItem = LayerPool.get();
pool = new LinkedList<PoolItem>();
pool.add(curItem);
PolygonLayer(int layer, Area area) {
super(layer);
this.area = area;
curItem = VertexPool.get();
pool = curItem;
}
void addPolygon(float[] points, int pos, int length) {

View File

@ -22,50 +22,20 @@ import java.nio.ShortBuffer;
import org.mapsforge.android.utils.FastMath;
import org.mapsforge.core.Tile;
import android.util.SparseArray;
class PolygonLayers {
private static final int NUM_VERTEX_FLOATS = 2;
private static final float[] mFillCoords = { -2, Tile.TILE_SIZE + 1,
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 short[] mByteFillCoords = null;
private SparseArray<PolygonLayer> layers;
PolygonLayer[] array = null;
int size;
PolygonLayers() {
layers = new SparseArray<PolygonLayer>(10);
size = 4;
}
PolygonLayer getLayer(int layer, int color, int fade) {
PolygonLayer l = layers.get(layer);
if (l != null) {
// if (color == l.color)
return l;
// return getLayer(layer + 1, color, fade);
}
l = new PolygonLayer(layer, color, fade);
layers.put(layer, l);
return l;
}
FloatBuffer compileLayerData(FloatBuffer buf) {
static FloatBuffer compileLayerData(PolygonLayer layers, FloatBuffer buf) {
FloatBuffer fbuf = buf;
int size = 4;
array = new PolygonLayer[layers.size()];
for (int i = 0, n = layers.size(); i < n; i++) {
PolygonLayer l = layers.valueAt(i);
array[i] = l;
for (PolygonLayer l = layers; l != null; l = l.next)
size += l.verticesCnt;
}
size *= NUM_VERTEX_FLOATS;
@ -81,38 +51,40 @@ class PolygonLayers {
fbuf.put(mFillCoords, 0, 8);
int pos = 4;
for (int i = 0, n = array.length; i < n; i++) {
PolygonLayer l = array[i];
PoolItem last = null, items = null;
for (PoolItem item : l.pool) {
for (PolygonLayer l = layers; l != null; l = l.next) {
for (PoolItem item = l.pool; item != null; item = item.next) {
fbuf.put(item.vertices, 0, item.used);
last = item;
}
l.offset = pos;
pos += l.verticesCnt;
LayerPool.add(l.pool);
if (last != null) {
last.next = items;
items = l.pool;
}
l.pool = null;
}
fbuf.flip();
VertexPool.add(items);
// not needed for drawing
layers = null;
fbuf.flip();
return fbuf;
}
ShortBuffer compileLayerData(ShortBuffer buf) {
static final short[] tmpItem = new short[PoolItem.SIZE];
static ShortBuffer compileLayerData(PolygonLayer layers, ShortBuffer buf) {
ShortBuffer sbuf = buf;
int size = 4;
array = new PolygonLayer[layers.size()];
for (int i = 0, n = layers.size(); i < n; i++) {
PolygonLayer l = layers.valueAt(i);
array[i] = l;
for (PolygonLayer l = layers; l != null; l = l.next)
size += l.verticesCnt;
}
size *= NUM_VERTEX_FLOATS;
@ -124,7 +96,7 @@ class PolygonLayers {
sbuf.clear();
}
short[] data = new short[PoolItem.SIZE];
short[] data = tmpItem;
if (mByteFillCoords == null) {
mByteFillCoords = new short[8];
@ -141,27 +113,38 @@ class PolygonLayers {
sbuf.put(mByteFillCoords, 0, 8);
int pos = 4;
for (int i = 0, n = array.length; i < n; i++) {
PolygonLayer l = array[i];
PoolItem last = null, items = null;
for (int k = 0, m = l.pool.size(); k < m; k++) {
PoolItem item = l.pool.get(k);
for (PolygonLayer l = layers; l != null; l = l.next) {
for (PoolItem item = l.pool; item != null; item = item.next) {
PoolItem.toHalfFloat(item, data);
sbuf.put(data, 0, item.used);
last = item;
}
l.offset = pos;
pos += l.verticesCnt;
LayerPool.add(l.pool);
if (last != null) {
last.next = items;
items = l.pool;
}
l.pool = null;
}
sbuf.flip();
VertexPool.add(items);
// not needed for drawing
layers = null;
sbuf.flip();
return sbuf;
}
static void clear(PolygonLayer layers) {
for (PolygonLayer l = layers; l != null; l = l.next) {
if (l.pool != null)
VertexPool.add(l.pool);
}
}
}

View File

@ -24,13 +24,14 @@ import java.nio.IntBuffer;
class PoolItem {
final float[] vertices;
int used;
PoolItem next;
PoolItem() {
vertices = new float[SIZE];
used = 0;
}
static int SIZE = 256;
static int SIZE = 128;
private static final float FLOAT_HALF_PREC = 5.96046E-8f;
private static final float FLOAT_HALF_MAX = 65504f;

View File

@ -23,6 +23,8 @@ class Shaders {
+ "attribute vec2 a_st;"
+ "varying vec2 v_st;"
+ "void main() {"
// + " gl_Position = u_center * vec4(a_position.x, a_position.y, 0.0, 1.0);"
// + " v_st = a_position.zw;"
+ " gl_Position = u_center * a_position;"
+ " v_st = a_st;"
+ "}";

View File

@ -0,0 +1,35 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.android.glrenderer;
import org.mapsforge.android.rendertheme.renderinstruction.Caption;
public class TextItem {
TextItem next;
final float x, y;
final String text;
final Caption caption;
final float width;
public TextItem(float x, float y, String text, Caption caption) {
this.x = x;
this.y = y;
this.text = text;
this.caption = caption;
this.width = caption.paint.measureText(text);
}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.android.glrenderer;
import java.util.ArrayList;
import org.mapsforge.android.rendertheme.renderinstruction.Caption;
public class TextLayer {
public ArrayList<TextItem> labels;
void addLabel(float x, float y, String text, Caption caption) {
}
}

View File

@ -0,0 +1,405 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.android.glrenderer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import org.mapsforge.android.utils.GlUtils;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.util.Log;
public class TextRenderer {
private final static int TEXTURE_WIDTH = 512;
private final static int TEXTURE_HEIGHT = 256;
final static int MAX_LABELS = 30;
private final Bitmap mBitmap;
private final Canvas mCanvas;
private int mFontPadX = 1;
private int mFontPadY = 1;
private int mBitmapFormat;
private int mBitmapType;
private ByteBuffer mByteBuffer;
private FloatBuffer mFloatBuffer;
private TextTexture[] mTextures;
private int mIndicesVBO;
private int mVerticesVBO;
final static int INDICES_PER_SPRITE = 6; // Indices Per Sprite
final static int VERTICES_PER_SPRITE = 4; // Vertices Per Sprite
final static int FLOATS_PER_VERTICE = 4;
private static int mTextProgram;
static int mTextUVPMatrixLocation;
static int mTextVertexLocation;
static int mTextTextureCoordLocation;
static int mTextUColorLocation;
static Paint mPaint = new Paint(Color.BLACK);
boolean debug = false;
float[] debugVertices = {
0, 0,
0, 1,
0, TEXTURE_HEIGHT - 1,
0, 0,
TEXTURE_WIDTH - 1, 0,
1, 1,
TEXTURE_WIDTH - 1, TEXTURE_HEIGHT - 1,
1, 0,
};
TextRenderer(int numTextures) {
mBitmap = Bitmap
.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mBitmapFormat = GLUtils.getInternalFormat(mBitmap);
mBitmapType = GLUtils.getType(mBitmap);
mTextProgram = GlUtils.createProgram(textVertexShader, textFragmentShader);
mTextUVPMatrixLocation = GLES20.glGetUniformLocation(mTextProgram, "mvp");
mTextUColorLocation = GLES20.glGetUniformLocation(mTextProgram, "col");
mTextVertexLocation = GLES20.glGetAttribLocation(mTextProgram, "vertex");
mTextTextureCoordLocation = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
// mVertexBuffer = new float[];
int bufferSize = numTextures
* MAX_LABELS * VERTICES_PER_SPRITE
* FLOATS_PER_VERTICE * (Float.SIZE / 8);
mByteBuffer = ByteBuffer.allocateDirect(bufferSize)
.order(ByteOrder.nativeOrder());
mFloatBuffer = mByteBuffer.asFloatBuffer();
int[] textureIds = new int[numTextures];
TextTexture[] textures = new TextTexture[numTextures];
GLES20.glGenTextures(numTextures, textureIds, 0);
for (int i = 0; i < numTextures; i++) {
// setup filters for texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[i]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
GLES20.GL_CLAMP_TO_EDGE); // Set U Wrapping
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_CLAMP_TO_EDGE); // Set V Wrapping
// load the generated bitmap onto the texture
// GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBitmap, 0);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBitmapFormat, mBitmap,
mBitmapType, 0);
textures[i] = new TextTexture(textureIds[i]);
}
GlUtils.checkGlError("init textures");
mTextures = textures;
// Setup triangle indices
short[] indices = new short[MAX_LABELS * INDICES_PER_SPRITE];
int len = indices.length;
short j = 0;
for (int i = 0; i < len; i += INDICES_PER_SPRITE, j += VERTICES_PER_SPRITE) {
indices[i + 0] = (short) (j + 0);
indices[i + 1] = (short) (j + 1);
indices[i + 2] = (short) (j + 2);
indices[i + 3] = (short) (j + 2);
indices[i + 4] = (short) (j + 3);
indices[i + 5] = (short) (j + 0);
}
ShortBuffer tmpIndices = mByteBuffer.asShortBuffer();
tmpIndices.put(indices, 0, len);
tmpIndices.flip();
int[] mVboIds = new int[2];
GLES20.glGenBuffers(2, mVboIds, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mVboIds[0]);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, len * (Short.SIZE / 8),
tmpIndices,
GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
mIndicesVBO = mVboIds[0];
mVerticesVBO = mVboIds[1];
}
boolean drawToTexture(GLMapTile tile) {
TextTexture tex = null;
if (tile.labels.size() == 0)
return false;
for (int i = 0; i < mTextures.length; i++) {
tex = mTextures[i];
if (tex.tile == null)
break;
if (!tex.tile.isActive)
break;
tex = null;
}
if (tex == null) {
Log.d(TAG, "no textures left");
return false;
}
if (tex.tile != null)
tex.tile.texture = null;
// if (debug)
// mBitmap.eraseColor(0xaa0000aa);
// else
mBitmap.eraseColor(Color.TRANSPARENT);
int pos = 0;
float[] buf = tex.vertices;
float xx = mFontPadX;
float yy = 0;
float width, height;
float y = 0;
float x = 0;
int max = tile.labels.size();
if (max > MAX_LABELS)
max = MAX_LABELS;
if (debug) {
mCanvas.drawLine(debugVertices[0], debugVertices[1], debugVertices[4],
debugVertices[5], mPaint);
mCanvas.drawLine(debugVertices[0], debugVertices[1], debugVertices[8],
debugVertices[9], mPaint);
mCanvas.drawLine(debugVertices[12], debugVertices[13], debugVertices[4],
debugVertices[5], mPaint);
mCanvas.drawLine(debugVertices[12], debugVertices[13], debugVertices[8],
debugVertices[9], mPaint);
}
int advanceY = 0;
// int advanceX = 0;
for (int i = 0; i < max; i++) {
TextItem t = tile.labels.get(i);
height = (int) (t.caption.fontHeight) + 2 * mFontPadY;
width = t.width + 2 * mFontPadX;
if (height > advanceY)
advanceY = (int) height;
if (xx + width > TEXTURE_WIDTH) {
xx = mFontPadX;
y += advanceY;
advanceY = (int) height;
}
yy = y + (height - 1) - t.caption.fontDescent - mFontPadY;
if (t.caption.stroke != null)
mCanvas.drawText(t.text, xx + t.width / 2, yy, t.caption.stroke);
mCanvas.drawText(t.text, xx + t.width / 2, yy, t.caption.paint);
// Log.d(TAG, "draw: " + t.text + " at:" + (xx + t.width / 2) + " " + yy + " w:"
// + t.width + " " + cellHeight);
if (width > TEXTURE_WIDTH)
width = TEXTURE_WIDTH;
float halfWidth = width / 2.0f;
float halfHeight = height / 2.0f;
float x1 = t.x - halfWidth;
float y1 = t.y - halfHeight;
float x2 = t.x + halfWidth;
float y2 = t.y + halfHeight;
float u1 = xx / TEXTURE_WIDTH;
float v1 = y / TEXTURE_HEIGHT;
float u2 = u1 + (width / TEXTURE_WIDTH);
float v2 = v1 + (height / TEXTURE_HEIGHT);
buf[pos++] = x1;
buf[pos++] = y1;
buf[pos++] = u1;
buf[pos++] = v2;
buf[pos++] = x2;
buf[pos++] = y1;
buf[pos++] = u2;
buf[pos++] = v2;
buf[pos++] = x2;
buf[pos++] = y2;
buf[pos++] = u2;
buf[pos++] = v1;
buf[pos++] = x1;
buf[pos++] = y2;
buf[pos++] = u1;
buf[pos++] = v1;
// yy += cellHeight;
// x += width;
xx += width;
// y += cellHeight;
if (y > TEXTURE_HEIGHT) {
Log.d(TAG, "reached max labels");
break;
}
}
tex.length = pos;
tile.texture = tex;
tex.tile = tile;
// GlUtils.checkGlError("0");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex.id);
// GlUtils.checkGlError("1");
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mBitmap, mBitmapFormat,
mBitmapType);
// GlUtils.checkGlError("2");
return true;
}
private static String TAG = "TextRenderer";
void compileTextures() {
int offset = 0;
TextTexture tex;
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
mFloatBuffer.clear();
for (int i = 0; i < mTextures.length; i++) {
tex = mTextures[i];
if (tex.tile == null || !tex.tile.isActive)
continue;
mFloatBuffer.put(tex.vertices, 0, tex.length);
tex.offset = offset;
offset += tex.length;
}
mFloatBuffer.flip();
// Log.d(TAG, "compileTextures" + mFloatBuffer.remaining() + " " + offset);
// TODO use sub-bufferdata function
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, offset * (Float.SIZE / 8),
mFloatBuffer, GLES20.GL_DYNAMIC_DRAW);
}
void beginDraw() {
GLES20.glUseProgram(mTextProgram);
GLES20.glEnableVertexAttribArray(mTextTextureCoordLocation);
GLES20.glEnableVertexAttribArray(mTextVertexLocation);
if (debug) {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
mFloatBuffer.clear();
mFloatBuffer.put(debugVertices, 0, 16);
mFloatBuffer.flip();
GLES20.glVertexAttribPointer(mTextVertexLocation, 2,
GLES20.GL_FLOAT, false, 16, mFloatBuffer);
mFloatBuffer.position(2);
GLES20.glVertexAttribPointer(mTextTextureCoordLocation, 2,
GLES20.GL_FLOAT, false, 16, mFloatBuffer);
} else {
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
}
}
void endDraw() {
GLES20.glDisableVertexAttribArray(mTextTextureCoordLocation);
GLES20.glDisableVertexAttribArray(mTextVertexLocation);
}
void drawTile(GLMapTile tile, float[] matrix) {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tile.texture.id);
GlUtils.checkGlError("bind");
GLES20.glUniformMatrix4fv(mTextUVPMatrixLocation, 1, false, matrix, 0);
GlUtils.checkGlError("matrix");
if (debug) {
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
} else {
GLES20.glVertexAttribPointer(mTextVertexLocation, 2,
GLES20.GL_FLOAT, false, 16, tile.texture.offset * 4);
GLES20.glVertexAttribPointer(mTextTextureCoordLocation, 2,
GLES20.GL_FLOAT, false, 16, tile.texture.offset * 4 + 8);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tile.texture.length / 16) *
INDICES_PER_SPRITE, GLES20.GL_UNSIGNED_SHORT, 0);
}
}
private static String textVertexShader = ""
+ "precision highp float; "
+ "attribute vec4 vertex;"
+ "attribute vec2 tex_coord;"
+ "uniform mat4 mvp;"
+ "varying vec2 tex_c;"
+ "void main() {"
+ " gl_Position = mvp * vertex;"
+ " tex_c = tex_coord;"
+ "}";
private static String textFragmentShader = ""
+ "precision highp float;"
+ "uniform sampler2D tex;"
+ "uniform vec4 col;"
+ "varying vec2 tex_c;"
+ "void main() {"
+ " gl_FragColor = texture2D(tex, tex_c);"
+ "}";
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.android.glrenderer;
public class TextTexture {
final float[] vertices;
final int id;
int length;
int offset;
GLMapTile tile;
String[] text;
TextTexture(int textureID) {
vertices = new float[TextRenderer.MAX_LABELS * 16];
id = textureID;
}
}

View File

@ -15,40 +15,62 @@
package org.mapsforge.android.glrenderer;
import java.util.LinkedList;
import android.annotation.SuppressLint;
class LayerPool {
static private LinkedList<PoolItem> pool = null;
static private int count;
class VertexPool {
private static final int POOL_LIMIT = 8192;
@SuppressLint("UseValueOf")
private static final Boolean lock = new Boolean(true);
static private PoolItem pool = null;
static private int count = 0;
static void init() {
if (pool == null) {
pool = new LinkedList<PoolItem>();
count = 0;
}
}
static PoolItem get() {
synchronized (pool) {
synchronized (lock) {
if (count == 0)
return new PoolItem();
count--;
PoolItem it = pool.pop();
PoolItem it = pool;
pool = pool.next;
it.used = 0;
it.next = null;
return it;
}
}
static void add(LinkedList<PoolItem> items) {
synchronized (pool) {
int size = items.size();
static void add(PoolItem items) {
if (items == null)
return;
while (count < 4096 && size-- > 0) {
synchronized (lock) {
PoolItem last = items;
// limit pool items
while (count < POOL_LIMIT) {
if (last.next == null) {
break;
}
last = last.next;
count++;
pool.add(items.pop());
}
// clear references
PoolItem tmp2, tmp = last.next;
while (tmp != null) {
tmp2 = tmp;
tmp = tmp.next;
tmp2.next = null;
}
last.next = pool;
pool = items;
}
}
}

View File

@ -19,6 +19,7 @@ import org.mapsforge.core.Tile;
import android.content.Context;
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
@ -59,7 +60,8 @@ public class TouchHandler {
mMapView = mapView;
mMapMoveDelta = viewConfiguration.getScaledTouchSlop();
mActivePointerId = INVALID_POINTER_ID;
mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener(mMapView));
mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener(
mMapView));
mGestureDetector = new GestureDetector(new MapGestureDetector(mMapView));
}
@ -90,7 +92,8 @@ public class TouchHandler {
boolean scaling = mScaleGestureDetector.isInProgress();
if (!scaling && !mMoveThresholdReached) {
if (Math.abs(moveX) > 3 * mMapMoveDelta || Math.abs(moveY) > 3 * mMapMoveDelta) {
if (Math.abs(moveX) > 3 * mMapMoveDelta
|| Math.abs(moveY) > 3 * mMapMoveDelta) {
// the map movement threshold has been reached
// longPressDetector.pressStop();
mMoveThresholdReached = true;
@ -179,15 +182,19 @@ public class TouchHandler {
return true;
}
private long lastRun = 0;
/**
* @param motionEvent
* ...
* @return ...
*/
public boolean handleMotionEvent(MotionEvent motionEvent) {
// workaround for a bug in the ScaleGestureDetector, see Android issue
// #12976
if (motionEvent.getAction() != MotionEvent.ACTION_MOVE || motionEvent.getPointerCount() > 1) {
if (motionEvent.getAction() != MotionEvent.ACTION_MOVE
|| motionEvent.getPointerCount() > 1) {
mScaleGestureDetector.onTouchEvent(motionEvent);
}
@ -197,23 +204,44 @@ public class TouchHandler {
// // return true;
// }
int action = getAction(motionEvent);
boolean ret = false;
if (action == MotionEvent.ACTION_DOWN) {
return onActionDown(motionEvent);
ret = onActionDown(motionEvent);
} else if (action == MotionEvent.ACTION_MOVE) {
return onActionMove(motionEvent);
ret = onActionMove(motionEvent);
} else if (action == MotionEvent.ACTION_UP) {
return onActionUp(motionEvent);
ret = onActionUp(motionEvent);
} else if (action == MotionEvent.ACTION_CANCEL) {
return onActionCancel();
ret = onActionCancel();
// } else if (action == MotionEvent.ACTION_POINTER_DOWN) {
// return onActionPointerDown(motionEvent);
} else if (action == MotionEvent.ACTION_POINTER_UP) {
return onActionPointerUp(motionEvent);
ret = onActionPointerUp(motionEvent);
}
// if (ret) {
// Log.d("", "" + );
//
// // try {
// //
// // Thread.sleep(10);
// // } catch (InterruptedException e) {
// // // TODO Auto-generated catch block
// // // e.printStackTrace();
// // }
//
// }
if (ret) {
// throttle input
long diff = SystemClock.uptimeMillis() - lastRun;
if (diff < 16) {
// Log.d("", "" + diff);
SystemClock.sleep(16 - diff);
}
lastRun = SystemClock.uptimeMillis();
}
// the event was not handled
return false;
return ret;
}
class MapGestureDetector extends SimpleOnGestureListener {
@ -254,7 +282,8 @@ public class TouchHandler {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
int w = Tile.TILE_SIZE * 20;
int h = Tile.TILE_SIZE * 20;
mPrevX = 0;
@ -265,7 +294,8 @@ public class TouchHandler {
mTimer = null;
}
mScroller.fling(0, 0, Math.round(velocityX) / 2, Math.round(velocityY) / 2, -w, w, -h, h);
mScroller.fling(0, 0, Math.round(velocityX) / 2, Math.round(velocityY) / 2,
-w, w, -h, h);
// animate for two seconds
mTimer = new CountDownTimer(2000, 20) {
@Override

View File

@ -15,6 +15,7 @@
package org.mapsforge.android.rendertheme;
import org.mapsforge.android.rendertheme.renderinstruction.Area;
import org.mapsforge.android.rendertheme.renderinstruction.Caption;
import org.mapsforge.android.rendertheme.renderinstruction.Line;
import android.graphics.Bitmap;
@ -37,14 +38,8 @@ public interface IRenderCallback {
*
* @param caption
* the text to be rendered.
* @param verticalOffset
* the vertical offset of the caption.
* @param paint
* the paint to be used for rendering the text.
* @param stroke
* an optional paint for the text casing (may be null).
*/
void renderAreaCaption(String caption, float verticalOffset, Paint paint, Paint stroke);
void renderAreaCaption(Caption caption);
/**
* Renders an area symbol with the given bitmap.
@ -59,14 +54,8 @@ public interface IRenderCallback {
*
* @param caption
* the text to be rendered.
* @param verticalOffset
* the vertical offset of the caption.
* @param paint
* the paint to be used for rendering the text.
* @param stroke
* an optional paint for the text casing (may be null).
*/
void renderPointOfInterestCaption(String caption, float verticalOffset, Paint paint, Paint stroke);
void renderPointOfInterestCaption(Caption caption);
/**
* Renders a point of interest circle with the given parameters.

View File

@ -140,7 +140,7 @@ public class RenderTheme {
public void matchNode(IRenderCallback renderCallback, Tag[] tags, byte zoomLevel) {
// List<RenderInstruction> matchingList = matchingListNode;
// MatchingCacheKey matchingCacheKey = matchingCacheKeyNode;
//
// if (!changed) {
// if (matchingList != null) {
// for (int i = 0, n = matchingList.size(); i < n; ++i) {
@ -158,11 +158,13 @@ public class RenderTheme {
// matchingList.get(i).renderNode(renderCallback, tags);
// }
// } else {
// // cache miss
// cache miss
// matchingList = new ArrayList<RenderInstruction>();
// for (int i = 0, n = mRulesList.size(); i < n; ++i) {
// mRulesList.get(i).matchNode(renderCallback, tags, zoomLevel, matchingList);
// }
for (int i = 0, n = mRulesList.size(); i < n; ++i) {
mRulesList.get(i).matchNode(renderCallback, tags, zoomLevel);
// , matchingList
}
// matchingCacheNodes.put(matchingCacheKey, matchingList);
// }
//
@ -214,7 +216,7 @@ public class RenderTheme {
public synchronized RenderInstruction[] matchWay(IRenderCallback renderCallback,
Tag[] tags,
byte zoomLevel,
boolean closed, boolean changed) {
boolean closed, boolean render) {
RenderInstruction[] renderInstructions = null;
LRUCache<MatchingCacheKey, RenderInstruction[]> matchingCache;
@ -240,12 +242,6 @@ public class RenderTheme {
boolean found = matchingCache.containsKey(matchingCacheKey);
if (found) {
renderInstructions = matchingCache.get(matchingCacheKey);
if (renderInstructions != null) {
for (int i = 0, n = renderInstructions.length; i < n; i++)
renderInstructions[i].renderWay(renderCallback, tags);
}
} else {
// cache miss
int c = (closed ? Closed.YES : Closed.NO);
@ -259,13 +255,17 @@ public class RenderTheme {
renderInstructions = new RenderInstruction[matchingList.size()];
for (int i = 0, n = matchingList.size(); i < n; ++i) {
RenderInstruction renderInstruction = matchingList.get(i);
renderInstruction.renderWay(renderCallback, tags);
renderInstructions[i] = renderInstruction;
}
}
matchingCache.put(matchingCacheKey, renderInstructions);
}
if (render && renderInstructions != null) {
for (int i = 0, n = renderInstructions.length; i < n; i++)
renderInstructions[i].renderWay(renderCallback, tags);
}
// mRenderInstructions = renderInstructions;
return renderInstructions;
}

View File

@ -5,29 +5,36 @@
version="1" map-background="#f0f0f0">
<!-- ways -->
<rule e="way" k="*" v="*">
<rule e="way" k="*" v="*" >
<!-- landuse -->
<rule e="way" k="natural" v="grassland|scrub" zoom-min="9">
<area fill="#ebf2d2" fade="10" />
</rule>
<!-- landuse base -->
<rule e="way" k="landuse" v="*">
<rule e="way" k="*" v="farmland|farm">
<rule e="way" k="*" v="military">
<area fill="#dddddd"/>
<line stroke="#666666" stroke-width="1.5" fixed="true"/>
</rule>
<rule e="way" k="*" v="farmland|farm|orchard|vine_yard|greenhouse_horticulture|plant_nursery">
<area fill="#fff8bf" fade="10" />
</rule>
<rule e="way" k="landuse" v="grass">
<area fill="#deecb9" fade="10" />
<!-- Steinbruch, Schotter-, Kies-, Sand- und Tongrube -->
<rule e="way" k="*" v="quarry">
<area fill="#ddddcc" fade="10" />
</rule>
<rule e="way" k="*" v="residential|farmyard|retail|commercial">
<area fill="#efefeb" fade="10" />
</rule>
<!-- <rule e="way" k="landuse" v="industrial|brownfield|railway"> <area
fill="#bcaacd" stroke="#e4e4e4" stroke-width="0.2" /> -->
<rule e="way" k="*" v="industrial|railway"> <area
fill="#e8e3e4" stroke="#e4e4e4" stroke-width="0.2" fade="10" />
</rule>
<!--<rule e="way" k="landuse" v="construction|greenfield"> <area fill="#a47c41"
stroke="#e4e4e4" stroke-width="0.2" /> </rule> -->
<!-- <rule e="way" k="landuse" v="garages"> <area fill="#d6d6e4" /> </rule> -->
</rule>
<rule e="way" k="outline" v="*">
@ -99,15 +106,16 @@
</rule>
</rule>
</rule>
<!-- landuse -->
<rule e="way" k="landuse" v="*" >
<rule e="way" k="landuse" v="*" zoom-min="10">
<!-- <rule e="way" k="*" v="landfill|quarry"> <area fill="#e9dd72" stroke="#556b2f"
stroke-width="0.2" /> </rule> -->
<rule e="way" k="*" v="cemetery">
<area fill="#d7e6b0" />
</rule>
<rule e="way" k="*" v="meadow|scrub">
<area fill="#deecb9" />
<rule e="way" k="*" v="meadow">
<area fill="#ebf2d2" fade="10"/>
</rule>
<!-- <rule e="way" k="*" v="village_green|recreation_ground">
@ -122,7 +130,12 @@
</rule>
<rule e="way" k="leisure|landuse" v="allotments|village_green|recreation_ground|garden|golf_course|dog_park" zoom-min="12">
<!-- garden -->
<rule e="way" k="leisure" v="golf_course|dog_park" zoom-min="12">
<area fill="#e7f7c1" fade="12" />
</rule>
<rule e="way" k="landuse" v="allotments|village_green|recreation_ground" zoom-min="12">
<area fill="#e7f7c1" fade="12" />
</rule>
@ -132,19 +145,35 @@
<area fill="#d7e6b0" fade="12" />
</rule>
</rule>
<rule e="way" k="natural|landuse" v="forest|wood" zoom-min="9">
<!-- <area fill="#BCCBB0" fade="10" /> -->
<!-- <rule e="way" k="*" v="*" zoom-max="11"> -->
<area fill="#d3dec8" fade="9" />
<!-- </rule> -->
<!-- <rule e="way" k="*" v="*" zoom-min="12">
<area fill="#cde2bc" fade="12" />
</rule> -->
<!-- <area fill="#87a670" fade="10" /> -->
<rule e="way" k="natural|" v="*">
<rule e="way" k="*" v="wood">
<rule e="way" k="*" v="*" zoom-max="12">
<area fill="#ebefe5" fade="7" />
</rule>
<rule e="way" k="*" v="*" zoom-min="11">
<area fill="#d3dec8" fade="12" />
</rule>
</rule>
</rule>
<rule e="way" k="landuse" v="*">
<rule e="way" k="*" v="forest">
<rule e="way" k="*" v="*" zoom-max="12">
<area fill="#ebefe5" fade="7" />
</rule>
<rule e="way" k="*" v="*" zoom-min="11">
<area fill="#d3dec8" fade="12" />
</rule>
</rule>
</rule>
<!-- keep grass above forest:wood and leisure:park! -->
<rule e="way" k="landuse" v="grass">
<area fill="#ebf2d2" fade="10" />
</rule>
<!-- amenity -->
<rule e="way" k="amenity" v="*">
@ -181,7 +210,7 @@
<rule e="way" k="*" zoom-min="12" v="heath">
<area fill="#ffffc0" fade="12" />
</rule>
<rule e="way" k="*" v="marsh|wetland">
<rule e="way" k="*" v="marsh|wetland|mud">
<area fill="#deecb9" fade="12" />
</rule>
</rule>
@ -190,14 +219,23 @@
<!-- leisure -->
<rule e="way" k="leisure" v="*" zoom-min="13">
<!-- playground| -->
<rule e="way" k="*" v="stadium" zoom-min="14">>
<line stroke="#c9c3c1" stroke-width="0.6" fixed="true" stroke-linecap="butt" />
<area fill="#e9e6e3" fade="15" />
</rule>
<!-- sollte unter playing field sein -->
<rule e="way" k="*" zoom_min="14" v="sports_centre|water_park">
<rule e="way" k="*" zoom-min="14" v="sports_centre|water_park">
<area fill="#daefdb" fade="12" />
</rule>
<rule e="way" k="*" v="*" zoom-min="15">
<rule e="way" k="*" v="*" zoom-min="14">
<rule e="way" k="*" v="playground|miniature_golf">
<area fill="#f4f4de" />
<line stroke="#fbdbc8" stroke-width="0.6" fixed="true"
stroke-linecap="butt" />
</rule>
<rule e="way" k="*" v="playing_fields|pitch">
<area fill="#f4f4de" />
<line stroke="#dbdbc8" stroke-width="0.6" fixed="true"
@ -235,10 +273,10 @@
<line stroke="#b4cbdc" stroke-width="0.275" stroke-linecap="butt" />
</rule>
<rule e="way" k="waterway" v="river" zoom-min="12">
<line stroke="#b4cbdc" stroke-width="1.0" stroke-linecap="butt" />
<line stroke="#b4cbdc" stroke-width="1.3" stroke-linecap="butt" />
</rule>
<rule e="way" k="waterway" v="river" zoom-max="11">
<line stroke="#b4cbdc" stroke-width="1.0" stroke-linecap="butt"
<line stroke="#b4cbdc" stroke-width="1.3" stroke-linecap="butt"
fixed="true" />
</rule>
<rule e="way" k="waterway" v="riverbank|dock">
@ -346,6 +384,8 @@
</rule> -->
</rule>
<rule e="way" k="outline" v="*">
<rule e="way" k="*" v="1">
<outline stroke="#909090" />
@ -371,30 +411,30 @@
<rule e="way" k="*" v="secondary|primary_link" zoom-min="9">
<!-- <line stroke="#eeee4a" stroke-width="1.8" stroke-linecap="butt"
fixed="true" /> -->
<line stroke="#f2df6d" stroke-width="1.9" stroke-linecap="butt"
fixed="true" />
<line stroke="#f2df6d" stroke-width="1.8" stroke-linecap="butt"
fixed="true" fade="9"/>
</rule>
<rule e="way" k="*" v="trunk_link|motorway_link" zoom-min="8">
<line stroke="#fed6a3" stroke-width="2.0" stroke-linecap="butt"
fixed="true" />
<line stroke="#fed6a3" stroke-width="1.8" stroke-linecap="butt"
fixed="true" fade="8"/>
</rule>
<rule e="way" k="*" v="primary" zoom-min="6">
<rule e="way" k="*" v="primary" zoom-min="5">
<!-- <line stroke="#eeee4a" stroke-width="1.4" stroke-linecap="butt"
fixed="true" /> -->
<line stroke="#f2df6d" stroke-width="2.0" stroke-linecap="butt"
fixed="true" />
<line stroke="#f2df6d" stroke-width="1.8" stroke-linecap="butt"
fixed="true" fade="5"/>
</rule>
<rule e="way" k="*" v="trunk" zoom-min="7">
<rule e="way" k="*" v="trunk" zoom-min="5">
<line stroke="#fed6a3" stroke-width="2.0" stroke-linecap="butt"
fixed="true" />
fixed="true" fade="5"/>
</rule>
<rule e="way" k="*" v="motorway">
<line stroke="#eec693" stroke-width="2.4" stroke-linecap="butt"
fixed="true" />
<line stroke="#eec693" stroke-width="2.2" stroke-linecap="butt"
fixed="true" fade="4"/>
</rule>
</rule>
@ -403,11 +443,11 @@
<rule e="way" k="*" v="*" zoom-min="15">
<rule e="way" k="*" v="steps">
<line stroke="#f1f0f4" stroke-width="0.35" outline="2"
<line stroke="#f1f0f4" stroke-width="0.25" outline="2"
stroke-linecap="butt" />
</rule>
<rule e="way" k="*" v="track|footway|path|cycleway" zoom-min="16">
<line stroke="#c1bcb6" stroke-width="0.30" stroke-linecap="butt" />
<line stroke="#c1bcb6" stroke-width="0.20" stroke-linecap="butt" />
</rule>
</rule>
@ -426,7 +466,7 @@
</rule>
<rule e="way" k="*" v="construction">
<line stroke="#d0d0d0" stroke-width="1.3" outline="1" />
<line stroke="#d0d0d0" stroke-width="1.2" outline="1" />
</rule>
</rule>
@ -434,10 +474,10 @@
<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" outline="2" stroke-linecap="butt" />
<line stroke="#ffffff" stroke-width="1.2" outline="2" stroke-linecap="butt" />
</rule>
<rule e="way" k="bridge" v="~|no|false">
<line stroke="#ffffff" stroke-width="1.3" outline="1" />
<line stroke="#ffffff" stroke-width="1.2" outline="1" />
</rule>
</rule>
@ -558,11 +598,11 @@
</rule>
<!-- railway casings and cores -->
<rule e="way" k="railway" v="tram">
<rule e="way" k="railway" v="tram" zoom-min="14">
<line stroke="#8c8f8c" stroke-width="0.8" fixed="true" />
</rule>
<rule e="way" k="railway" v="light_rail|subway|narrow_gauge">
<rule e="way" k="railway" v="light_rail|subway|narrow_gauge" zoom-min="14">
<line stroke="#a0a0a0" stroke-width="0.8" stroke-linecap="butt"
fixed="true" />
@ -579,6 +619,12 @@
<line stroke="#bbbbcc" stroke-width="0.6" stroke-linecap="butt"
fixed="true" />
</rule>
<!-- whatever railway:spur means ... -->
<rule e="way" k="railway" v="disused|spur|abandoned|preserved" >
<line stroke="#cccccc" stroke-width="0.6" stroke-linecap="butt"
fixed="true" />
</rule>
</rule>
</rule>
@ -634,6 +680,15 @@
<caption k="name" font-style="bold" font-size="10" fill="#000000"
stroke="#ffffff" stroke-width="2.0" />
</rule>
<rule e="way" k="debug" v="area">
<line stroke="#ff0000" stroke-width="1.2" fixed="true" stroke-linecap="butt" />
<area fill="#880000ff"/>
<caption k="name" font-size="15" fill="#ffffff" stroke="#000000" stroke-width="2.0"/>
</rule>
<rule e="way" k="debug" v="way">
<line stroke="#00ffff" stroke-width="1.5" fixed="true" stroke-linecap="butt" />
<caption k="name" font-size="15" fill="#ffffff" stroke="#000000" stroke-width="2.0"/>
</rule>
</rule>
<rule e="node" k="*" v="*">
@ -642,6 +697,10 @@
<circle r="1.5" fill="#909090" />
</rule>
<rule e="node" k="debug" v="*" >
<caption k="name" font-size="12" fill="#0000ff" />
</rule>
<!-- highway -->
<!-- <rule e="node" k="highway" v="*"> <rule e="node" k="highway" v="turning_circle">
@ -671,12 +730,12 @@
<caption k="name" font-style="bold" font-size="20" fill="#000000"
stroke="#ffffff" stroke-width="2.0" />
</rule>
<rule e="node" k="*" v="city" zoom-max="14">
<caption k="name" font-style="bold" font-size="25" fill="#000000"
<rule e="node" k="*" v="city">
<caption k="name" font-style="bold" font-size="20" fill="#000000"
stroke="#ffffff" stroke-width="2.0" />
</rule>
<rule e="node" k="*" v="country" zoom-max="6">
<caption k="name" font-style="bold" font-size="25" fill="#000000"
<rule e="node" k="*" v="country" zoom-max="7">
<caption k="name" font-size="20" fill="#000000"
stroke="#ffffff" stroke-width="2.0" />
</rule>
</rule>

View File

@ -42,7 +42,8 @@ public final class Area implements RenderInstruction {
* @throws IOException
* if an I/O error occurs while reading a resource.
*/
public static Area create(String elementName, Attributes attributes, int level) throws IOException {
public static Area create(String elementName, Attributes attributes, int level)
throws IOException {
String src = null;
int fill = Color.BLACK;
int stroke = Color.TRANSPARENT;
@ -73,7 +74,8 @@ public final class Area implements RenderInstruction {
private static void validate(float strokeWidth) {
if (strokeWidth < 0) {
throw new IllegalArgumentException("stroke-width must not be negative: " + strokeWidth);
throw new IllegalArgumentException("stroke-width must not be negative: "
+ strokeWidth);
}
}
@ -96,22 +98,24 @@ public final class Area implements RenderInstruction {
/**
*
*/
public final int color;
public final float color[];
/**
*
*/
public final int fade;
private Area(String src, int fill, int stroke, float strokeWidth, int fade, int level) throws IOException {
private Area(String src, int fill, int stroke, float strokeWidth, int fade, int level)
throws IOException {
super();
Shader shader = BitmapUtils.createBitmapShader(src);
if (fill == Color.TRANSPARENT) {
paintFill = null;
} else {
paintFill = new Paint(Paint.ANTI_ALIAS_FLAG);
paintFill.setShader(shader);
if (src != null) {
Shader shader = BitmapUtils.createBitmapShader(src);
paintFill.setShader(shader);
}
paintFill.setStyle(Style.FILL);
paintFill.setColor(fill);
paintFill.setStrokeCap(Cap.ROUND);
@ -125,7 +129,12 @@ public final class Area implements RenderInstruction {
paintOutline.setColor(stroke);
paintOutline.setStrokeCap(Cap.ROUND);
}
color = fill;
color = new float[4];
color[0] = (fill >> 16 & 0xff) / 255.0f;
color[1] = (fill >> 8 & 0xff) / 255.0f;
color[2] = (fill >> 0 & 0xff) / 255.0f;
color[3] = (fill >> 24 & 0xff) / 255.0f;
this.strokeWidth = strokeWidth;
this.fade = fade;
this.level = level;

View File

@ -24,8 +24,10 @@ import org.xml.sax.Attributes;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.graphics.Typeface;
import android.util.FloatMath;
/**
* Represents a text label on the map.
@ -78,41 +80,54 @@ public final class Caption implements RenderInstruction {
return new Caption(textKey, dy, typeface, fontSize, fill, stroke, strokeWidth);
}
private static void validate(String elementName, String textKey, float fontSize, float strokeWidth) {
private static void validate(String elementName, String textKey, float fontSize,
float strokeWidth) {
if (textKey == null) {
throw new IllegalArgumentException("missing attribute k for element: " + elementName);
throw new IllegalArgumentException("missing attribute k for element: "
+ elementName);
} else if (fontSize < 0) {
throw new IllegalArgumentException("font-size must not be negative: " + fontSize);
throw new IllegalArgumentException("font-size must not be negative: "
+ fontSize);
} else if (strokeWidth < 0) {
throw new IllegalArgumentException("stroke-width must not be negative: " + strokeWidth);
throw new IllegalArgumentException("stroke-width must not be negative: "
+ strokeWidth);
}
}
private final float mDy;
private final float mFontSize;
private final Paint mPaint;
private final Paint mStroke;
private final String mTextKey;
public final float dy;
public float fontSize;
public final Paint paint;
public final Paint stroke;
public final String textKey;
public final float fontHeight;
public final float fontDescent;
private Caption(String textKey, float dy, Typeface typeface, float fontSize, int fill, int stroke, float strokeWidth) {
private Caption(String textKey, float dy, Typeface typeface, float fontSize,
int fillColor, int strokeColor, float strokeWidth) {
super();
mTextKey = textKey;
mDy = dy;
this.textKey = textKey.intern();
this.dy = dy;
this.fontSize = fontSize;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setTextAlign(Align.LEFT);
mPaint.setTypeface(typeface);
mPaint.setColor(fill);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextAlign(Align.CENTER);
paint.setTypeface(typeface);
paint.setColor(fillColor);
mStroke = new Paint(Paint.ANTI_ALIAS_FLAG);
mStroke.setStyle(Style.STROKE);
mStroke.setTextAlign(Align.LEFT);
mStroke.setTypeface(typeface);
mStroke.setColor(stroke);
mStroke.setStrokeWidth(strokeWidth);
stroke = new Paint(Paint.ANTI_ALIAS_FLAG);
stroke.setStyle(Style.STROKE);
stroke.setTextAlign(Align.CENTER);
stroke.setTypeface(typeface);
stroke.setColor(strokeColor);
stroke.setStrokeWidth(strokeWidth);
mFontSize = fontSize;
paint.setTextSize(fontSize);
stroke.setTextSize(fontSize);
FontMetrics fm = paint.getFontMetrics();
fontHeight = FloatMath.ceil(Math.abs(fm.bottom) + Math.abs(fm.top));
fontDescent = FloatMath.ceil(Math.abs(fm.descent));
}
@Override
@ -122,12 +137,12 @@ public final class Caption implements RenderInstruction {
@Override
public void renderNode(IRenderCallback renderCallback, Tag[] tags) {
renderCallback.renderPointOfInterestCaption(mTextKey, mDy, mPaint, mStroke);
renderCallback.renderPointOfInterestCaption(this);
}
@Override
public void renderWay(IRenderCallback renderCallback, Tag[] tags) {
renderCallback.renderAreaCaption(mTextKey, mDy, mPaint, mStroke);
renderCallback.renderAreaCaption(this);
}
@Override
@ -137,7 +152,7 @@ public final class Caption implements RenderInstruction {
@Override
public void scaleTextSize(float scaleFactor) {
mPaint.setTextSize(mFontSize * scaleFactor);
mStroke.setTextSize(mFontSize * scaleFactor);
paint.setTextSize(fontSize * scaleFactor);
stroke.setTextSize(fontSize * scaleFactor);
}
}

View File

@ -55,7 +55,7 @@ public final class Line implements RenderInstruction {
float[] strokeDasharray = null;
Cap strokeLinecap = Cap.ROUND;
int outline = -1;
// int fade = -1;
int fade = -1;
boolean fixed = false;
for (int i = 0; i < attributes.getLength(); ++i) {
@ -75,7 +75,7 @@ public final class Line implements RenderInstruction {
} else if ("outline".equals(name)) {
outline = Integer.parseInt(value);
} else if ("fade".equals(name)) {
// fade = Integer.parseInt(value);
fade = Integer.parseInt(value);
} else if ("fixed".equals(name)) {
fixed = Boolean.parseBoolean(value);
} else {
@ -85,7 +85,7 @@ public final class Line implements RenderInstruction {
validate(strokeWidth);
return new Line(src, stroke, strokeWidth, strokeDasharray, strokeLinecap, level,
outline, fixed);
outline, fixed, fade);
}
private static void validate(float strokeWidth) {
@ -123,7 +123,7 @@ public final class Line implements RenderInstruction {
/**
*
*/
public final int color;
public final float color[];
/**
*
*/
@ -134,9 +134,11 @@ public final class Line implements RenderInstruction {
*/
public final boolean fixed;
public final int fade;
private Line(String src, int stroke, float strokeWidth, float[] strokeDasharray,
Cap strokeLinecap, int level,
int outline, boolean fixed)
int outline, boolean fixed, int fade)
throws IOException {
super();
@ -151,11 +153,18 @@ public final class Line implements RenderInstruction {
}
paint.setStrokeCap(strokeLinecap);
round = (strokeLinecap == Cap.ROUND);
this.color = stroke;
color = new float[4];
color[0] = (stroke >> 16 & 0xff) / 255.0f;
color[1] = (stroke >> 8 & 0xff) / 255.0f;
color[2] = (stroke >> 0 & 0xff) / 255.0f;
color[3] = (stroke >> 24 & 0xff) / 255.0f;
this.strokeWidth = strokeWidth;
this.level = level;
this.outline = outline;
this.fixed = fixed;
this.fade = fade;
}
@Override

View File

@ -22,6 +22,7 @@ import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.rendertheme.IRenderCallback;
import org.mapsforge.android.rendertheme.RenderTheme;
import org.mapsforge.android.rendertheme.renderinstruction.Area;
import org.mapsforge.android.rendertheme.renderinstruction.Caption;
import org.mapsforge.android.rendertheme.renderinstruction.Line;
import org.mapsforge.core.Tag;
import org.mapsforge.core.Tile;
@ -218,8 +219,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
}
@Override
public void renderAreaCaption(String textKey, float verticalOffset, Paint paint,
Paint stroke) {
public void renderAreaCaption(Caption caption) {
// mapDatabase.readTag(caption);
// if (caption.value != null) {
// float[] centerPosition = GeometryUtils
@ -241,7 +241,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
}
@Override
public void renderPointOfInterest(byte layer, int latitude, int longitude, Tag[] tags) {
public void renderPointOfInterest(byte layer, float latitude, float longitude,
Tag[] tags) {
mDrawingLayer = mWays[getValidLayer(layer)];
mPoiX = scaleLongitude(longitude);
mPoiY = scaleLatitude(latitude);
@ -249,8 +250,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
}
@Override
public void renderPointOfInterestCaption(String textKey, float verticalOffset,
Paint paint, Paint stroke) {
public void renderPointOfInterestCaption(Caption caption) {
// mapDatabase.readTag(caption);
// if (caption.value != null) {
// nodes.add(new PointTextContainer(caption.value, poiX, poiY + verticalOffset, paint, stroke));
@ -298,7 +298,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
// private byte mPrevLayer = 0;
@Override
public void renderWay(byte layer, Tag[] tags, float[] wayNodes, int[] wayLengths,
public void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLengths,
boolean changed) {
// if (mCoords == null)
// mCoords = mMapDatabase.getCoordinates();
@ -526,4 +526,10 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
// TODO Auto-generated method stub
}
@Override
public boolean checkWay(Tag[] tags, boolean closed) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -101,6 +101,7 @@ public class GlUtils {
int program = GLES20.glCreateProgram();
if (program != 0) {
checkGlError("glCreateProgram");
GLES20.glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
GLES20.glAttachShader(program, pixelShader);

View File

@ -587,9 +587,11 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
preferences.getBoolean("drawTileCoordinates", false);
boolean disablePolygons =
preferences.getBoolean("disablePolygons", false);
boolean drawUnmatchedWays =
preferences.getBoolean("drawUnmatchedWays", false);
DebugSettings debugSettings = new DebugSettings(drawTileCoordinates,
drawTileFrames, disablePolygons);
drawTileFrames, disablePolygons, drawUnmatchedWays);
mMapView.setDebugSettings(debugSettings);

View File

@ -58,11 +58,28 @@ public class Tag {
public Tag(String tag) {
int splitPosition = tag.indexOf(KEY_VALUE_SEPARATOR);
if (splitPosition < 0) {
System.out.println("TAG:" + tag);
}
this.key = tag.substring(0, splitPosition).intern();
this.value = tag.substring(splitPosition + 1).intern();
this.hashCodeValue = calculateHashCode();
}
public Tag(String tag, boolean hashValue) {
int splitPosition = tag.indexOf(KEY_VALUE_SEPARATOR);
if (splitPosition < 0) {
System.out.println("TAG:" + tag);
}
this.key = tag.substring(0, splitPosition).intern();
if (!hashValue)
this.value = tag.substring(splitPosition + 1);
else
this.value = tag.substring(splitPosition + 1).intern();
this.hashCodeValue = calculateHashCode();
}
/**
* @param key
* the key of the tag.
@ -75,6 +92,12 @@ public class Tag {
this.hashCodeValue = calculateHashCode();
}
public Tag(String key, String value, boolean intern) {
this.key = (key == null ? null : key);
this.value = (value == null ? null : value);
this.hashCodeValue = calculateHashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {

View File

@ -27,7 +27,7 @@ public class Tile {
/**
* Width and height of a map tile in pixel.
*/
public static final int TILE_SIZE = 256;
public static int TILE_SIZE = 256;
/**
* Size of a single uncompressed map tile bitmap in bytes.

View File

@ -36,8 +36,10 @@ public interface IMapDatabase {
* the tile to read.
* @param mapDatabaseCallback
* the callback which handles the extracted map elements.
* @return true if successful
*/
public abstract void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback);
public abstract QueryResult executeQuery(Tile tile,
IMapDatabaseCallback mapDatabaseCallback);
/**
* @return the metadata for the current map file.

View File

@ -33,7 +33,7 @@ public interface IMapDatabaseCallback {
* @param tags
* the tags of the node.
*/
void renderPointOfInterest(byte layer, int latitude, int longitude, Tag[] tags);
void renderPointOfInterest(byte layer, float latitude, float longitude, Tag[] tags);
/**
* Renders water background for the current tile.
@ -54,5 +54,9 @@ public interface IMapDatabaseCallback {
* @param changed
* tags have changed since last call (just an optional hint)
*/
void renderWay(byte layer, Tag[] tags, float[] wayNodes, int[] wayLength, boolean changed);
void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLength,
boolean changed);
boolean checkWay(Tag[] tags, boolean closed);
}

View File

@ -0,0 +1,22 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.database;
public enum QueryResult {
SUCCESS,
FAILED,
TILE_NOT_FOUND,
DELAYED,
}

View File

@ -24,6 +24,7 @@ import org.mapsforge.database.FileOpenResult;
import org.mapsforge.database.IMapDatabase;
import org.mapsforge.database.IMapDatabaseCallback;
import org.mapsforge.database.MapFileInfo;
import org.mapsforge.database.QueryResult;
/**
*
@ -33,9 +34,11 @@ public class MapDatabase implements IMapDatabase {
private final static String PROJECTION = "Mercator";
private float[] mCoords = new float[20];
private int[] mIndex = new int[2];
private short[] mIndex = new short[2];
// private Tag[] mTags = { new Tag("boundary", "administrative"), new Tag("admin_level", "2") };
private Tag[] mTags = { new Tag("natural", "water") };
private Tag[] mNameTags;
private final MapFileInfo mMapInfo =
new MapFileInfo(new BoundingBox(-180, -90, 180, 90),
new Byte((byte) 0), null, PROJECTION, 0, 0, 0, "de", "yo!", "by me");
@ -48,7 +51,7 @@ public class MapDatabase implements IMapDatabase {
// private static double HALF_PI = Math.PI / 2;
@Override
public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
public QueryResult executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
long cx = tile.pixelX + (Tile.TILE_SIZE >> 1);
long cy = tile.pixelY + (Tile.TILE_SIZE >> 1);
@ -140,6 +143,17 @@ public class MapDatabase implements IMapDatabase {
mIndex[1] = 10;
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, mIndex, true);
lon1 = (float) MercatorProjection.pixelXToLongitude(cx, tile.zoomLevel) * 1000000;
lat1 = (float) MercatorProjection.pixelXToLongitude(cx, tile.zoomLevel) * 1000000;
mNameTags = new Tag[2];
mNameTags[0] = new Tag("place", "city");
mNameTags[1] = new Tag("name", "check one check two, YO!");
mapDatabaseCallback.renderPointOfInterest((byte) 0, (int) lat1, (int) lon1,
mNameTags);
return QueryResult.SUCCESS;
}
@Override

View File

@ -26,6 +26,7 @@ import org.mapsforge.core.Tile;
import org.mapsforge.database.FileOpenResult;
import org.mapsforge.database.IMapDatabase;
import org.mapsforge.database.IMapDatabaseCallback;
import org.mapsforge.database.QueryResult;
import org.mapsforge.database.mapfile.header.MapFileHeader;
import org.mapsforge.database.mapfile.header.MapFileInfo;
import org.mapsforge.database.mapfile.header.SubFileParameter;
@ -203,9 +204,9 @@ public class MapDatabase implements IMapDatabase {
* org.mapsforge.map.reader.MapDatabaseCallback)
*/
@Override
public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
public QueryResult executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
if (sMapFileHeader == null)
return;
return QueryResult.FAILED;
if (mIntBuffer == null)
mIntBuffer = new int[MAXIMUM_WAY_NODES_SEQUENCE_LENGTH * 2];
@ -223,7 +224,7 @@ public class MapDatabase implements IMapDatabase {
if (subFileParameter == null) {
LOG.warning("no sub-file for zoom level: "
+ queryParameters.queryZoomLevel);
return;
return QueryResult.FAILED;
}
QueryCalculations.calculateBaseTiles(queryParameters, tile, subFileParameter);
@ -231,7 +232,9 @@ public class MapDatabase implements IMapDatabase {
processBlocks(mapDatabaseCallback, queryParameters, subFileParameter);
} catch (IOException e) {
LOG.log(Level.SEVERE, null, e);
return QueryResult.FAILED;
}
return QueryResult.SUCCESS;
}
/*
@ -580,6 +583,8 @@ public class MapDatabase implements IMapDatabase {
}
}
// Log.d("MapDatabase", "read POI");
// get the POI latitude offset (VBE-S)
int latitude = mTileLatitude + mReadBuffer.readSignedInt();
@ -610,12 +615,19 @@ public class MapDatabase implements IMapDatabase {
// check if the POI has a name
if ((featureByte & POI_FEATURE_NAME) != 0) {
mReadBuffer.getPositionAndSkip();
// int pos = mReadBuffer.getPositionAndSkip();
String str = mReadBuffer.readUTF8EncodedString();
Tag[] tmp = tags;
tags = new Tag[tmp.length + 1];
System.arraycopy(tmp, 0, tags, 0, tmp.length);
tags[tags.length - 1] = new Tag("name", str, false);
}
// check if the POI has a house number
if ((featureByte & POI_FEATURE_HOUSE_NUMBER) != 0) {
mReadBuffer.getPositionAndSkip();
// mReadBuffer.getPositionAndSkip();
String str = mReadBuffer.readUTF8EncodedString();
}
// check if the POI has an elevation
@ -632,7 +644,7 @@ public class MapDatabase implements IMapDatabase {
return true;
}
private int[] processWayDataBlock(boolean doubleDeltaEncoding) {
private short[] processWayDataBlock(boolean doubleDeltaEncoding) {
// get and check the number of way coordinate blocks (VBE-U)
int numBlocks = mReadBuffer.readUnsignedInt();
if (numBlocks < 1 || numBlocks > Short.MAX_VALUE) {
@ -640,7 +652,7 @@ public class MapDatabase implements IMapDatabase {
return null;
}
int[] wayLengths = new int[numBlocks];
short[] wayLengths = new short[numBlocks];
mWayNodePosition = 0;
@ -663,7 +675,7 @@ public class MapDatabase implements IMapDatabase {
} else {
len = decodeWayNodesSingleDelta(len);
}
wayLengths[coordinateBlock] = len;
wayLengths[coordinateBlock] = (short) len;
}
return wayLengths;
@ -907,7 +919,7 @@ public class MapDatabase implements IMapDatabase {
}
for (int wayDataBlock = 0; wayDataBlock < wayDataBlocks; ++wayDataBlock) {
int[] wayLengths = processWayDataBlock(featureWayDoubleDeltaEncoding);
short[] wayLengths = processWayDataBlock(featureWayDoubleDeltaEncoding);
if (wayLengths == null)
return false;

View File

@ -46,6 +46,7 @@ import org.mapsforge.database.FileOpenResult;
import org.mapsforge.database.IMapDatabase;
import org.mapsforge.database.IMapDatabaseCallback;
import org.mapsforge.database.MapFileInfo;
import org.mapsforge.database.QueryResult;
import android.util.Log;
@ -65,35 +66,36 @@ public class MapDatabase implements IMapDatabase {
// private static final String URL = "http://city.informatik.uni-bremen.de:8020/test/%d/%d/%d.osmtile";
private static final String URL = "http://city.informatik.uni-bremen.de/osmstache/test/%d/%d/%d.osmtile";
// private static final String URL = "http://city.informatik.uni-bremen.de/osmstache/gis2/%d/%d/%d.osmtile";
private static final Header encodingHeader =
new BasicHeader("Accept-Encoding", "gzip");
private static volatile HashMap<String, Tag> tagHash = new HashMap<String, Tag>(100);
private Tag[] curTags = new Tag[1000];
private Tag[] curTags = new Tag[250];
private int mCurTagCnt;
// private AndroidHttpClient mClient;
private HttpClient mClient;
private IMapDatabaseCallback mMapGenerator;
private float mScaleFactor;
private HttpGet mRequest = null;
@Override
public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
public QueryResult executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
mCanceled = false;
if (mClient == null)
createClient();
// Log.d(TAG, "get tile >> : " + tile);
String url = String.format(URL, Integer.valueOf(tile.zoomLevel),
Long.valueOf(tile.tileX), Long.valueOf(tile.tileY));
HttpGet getRequest = new HttpGet(url);
getRequest.addHeader(encodingHeader);
mRequest = getRequest;
mMapGenerator = mapDatabaseCallback;
mCurTagCnt = 0;
// using variable coordinate scalefactor to take advantage of
// variable byte encoded integers
// using variable coordinate scalefactor to take advantage of varint
mScaleFactor = 1 / 100f;
if (tile.zoomLevel < 12)
mScaleFactor = (float) Math.pow(2, (12 - tile.zoomLevel)) / 100f;
@ -101,22 +103,16 @@ public class MapDatabase implements IMapDatabase {
try {
HttpResponse response = mClient.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
final HttpEntity entity = response.getEntity();
if (statusCode != HttpStatus.SC_OK) {
Log.d(TAG, "Http response " + statusCode);
return;
entity.consumeContent();
return QueryResult.FAILED;
}
final HttpEntity entity = response.getEntity();
if (entity == null) {
Log.d(TAG, "Somethings wrong? - no entity " + statusCode);
return;
}
InputStream is = null;
GZIPInputStream zis = null;
try {
// is = AndroidHttpClient.getUngzippedContent(entity);
is = entity.getContent();
zis = new GZIPInputStream(is);
@ -131,12 +127,19 @@ public class MapDatabase implements IMapDatabase {
}
} catch (SocketException ex) {
Log.d(TAG, "Socket exception: " + ex.getMessage());
return QueryResult.FAILED;
} catch (SocketTimeoutException ex) {
Log.d(TAG, "Socket exception: " + ex.getMessage());
Log.d(TAG, "Socket Timeout exception: " + ex.getMessage());
return QueryResult.FAILED;
} catch (Exception ex) {
getRequest.abort();
ex.printStackTrace();
return QueryResult.FAILED;
}
mRequest = null;
// Log.d(TAG, "get tile << : " + tile);
return QueryResult.SUCCESS;
}
@Override
@ -163,7 +166,7 @@ public class MapDatabase implements IMapDatabase {
HttpConnectionParams.setConnectionTimeout(params, 10 * 1000);
HttpConnectionParams.setSoTimeout(params, 60 * 1000);
HttpConnectionParams.setSocketBufferSize(params, 8192);
HttpConnectionParams.setSocketBufferSize(params, 16384);
mClient = new DefaultHttpClient(params);
HttpClientParams.setRedirecting(params, false);
SchemeRegistry schemeRegistry = new SchemeRegistry();
@ -190,7 +193,7 @@ public class MapDatabase implements IMapDatabase {
return null;
}
private static final int BUFFER_SIZE = 65536;
private static final int BUFFER_SIZE = 65536 * 2;
private final byte[] buffer = new byte[BUFFER_SIZE];
private int bufferPos;
@ -200,14 +203,21 @@ public class MapDatabase implements IMapDatabase {
private static final int TAG_TILE_TAGS = 1;
private static final int TAG_TILE_WAYS = 2;
private static final int TAG_TILE_NODES = 3;
private static final int TAG_WAY_TAGS = 1;
private static final int TAG_WAY_INDEX = 2;
private static final int TAG_WAY_COORDS = 3;
private static final int TAG_WAY_LAYER = 4;
private static final int TAG_TILE_POLY = 3;
private static final int TAG_TILE_NODES = 4;
private static final int TAG_WAY_TAGS = 11;
private static final int TAG_WAY_INDEX = 12;
private static final int TAG_WAY_COORDS = 13;
private static final int TAG_WAY_LAYER = 21;
private static final int TAG_WAY_NUM_TAGS = 1;
private static final int TAG_WAY_NUM_INDICES = 2;
private static final int TAG_WAY_NUM_COORDS = 3;
// private static final int TAG_NODE_TAGS = 1;
// private static final int TAG_NODE_COORDS = 2;
private static final int TAG_NODE_TAGS = 11;
private static final int TAG_NODE_COORDS = 12;
private static final int TAG_NODE_LAYER = 21;
private static final int TAG_NODE_NUM_TAGS = 1;
private static final int TAG_NODE_NUM_COORDS = 2;
private boolean decode(InputStream is) throws IOException {
inputStream = is;
@ -228,7 +238,11 @@ public class MapDatabase implements IMapDatabase {
break;
case TAG_TILE_WAYS:
decodeTileWays();
decodeTileWays(false);
break;
case TAG_TILE_POLY:
decodeTileWays(true);
break;
case TAG_TILE_NODES:
@ -248,16 +262,23 @@ public class MapDatabase implements IMapDatabase {
Tag tag = tagHash.get(tagString);
if (tag == null) {
tag = new Tag(tagString);
// Log.d(TAG, "tag:" + tagString);
if (tagString.equals("name="))
tag = new Tag(tagString, false);
else
tag = new Tag(tagString);
tagHash.put(tagString, tag);
}
curTags[mCurTagCnt++] = tag;
// FIXME ...
if (mCurTagCnt < 250)
curTags[mCurTagCnt++] = tag;
// Log.d(TAG, "tag:" + tag);
//
return true;
}
private boolean decodeTileWays() throws IOException {
private boolean decodeTileWays(boolean polygon) throws IOException {
int bytes = decodeVarint32();
int end = bytesRead + bytes;
@ -265,6 +286,11 @@ public class MapDatabase implements IMapDatabase {
int tagCnt = 0;
int coordCnt = 0;
int layer = 0;
Tag[] tags = null;
short[] index = null;
boolean skip = false;
boolean fail = false;
while (bytesRead < end) {
// read tag and wire type
@ -275,54 +301,56 @@ public class MapDatabase implements IMapDatabase {
int tag = (val >> 3);
// int wireType = val & 7;
// Log.d(TAG, "way " + tag + " " + wireType + " bytes:" + bytes);
int cnt;
switch (tag) {
case TAG_WAY_TAGS:
tagCnt = decodeWayTags();
tags = decodeWayTags(tagCnt);
break;
case TAG_WAY_INDEX:
indexCnt = decodeWayIndices();
index = decodeWayIndices(indexCnt);
break;
case TAG_WAY_COORDS:
coordCnt = decodeWayCoordinates();
cnt = decodeWayCoordinates(skip);
if (cnt != coordCnt) {
Log.d(TAG, "EEEK wrong number of coordintes");
fail = true;
}
break;
case TAG_WAY_LAYER:
layer = decodeVarint32();
break;
case TAG_WAY_NUM_TAGS:
tagCnt = decodeVarint32();
break;
case TAG_WAY_NUM_INDICES:
indexCnt = decodeVarint32();
break;
case TAG_WAY_NUM_COORDS:
coordCnt = decodeVarint32();
break;
default:
Log.d(TAG, "invalid type for way: " + tag);
}
}
if (indexCnt == 0 || tagCnt == 0)
if (fail || index == null || tags == null || indexCnt == 0 || tagCnt == 0) {
Log.d(TAG, "..." + index + " " + tags + " " + indexCnt + " " + coordCnt + " "
+ tagCnt);
return false;
int[] index = new int[indexCnt];
int sum = 0;
for (int i = 0; i < indexCnt; i++) {
index[i] = tmpIndices[i] * 2;
sum += index[i];
}
Tag[] tags = new Tag[tagCnt];
for (int i = 0; i < tagCnt; i++)
tags[i] = curTags[tmpTags[i]];
float[] coords = tmpCoords;
int pos = 0;
if (coordCnt != sum) {
Log.d(TAG, "way length is wrong " + coordCnt + " " + sum);
return false;
}
float z = mScaleFactor;
for (int j = 0, m = indexCnt; j < m; j++) {
float lastX = 0;
@ -332,23 +360,86 @@ public class MapDatabase implements IMapDatabase {
lastX = coords[pos] = (coords[pos] * z) + lastX;
lastY = coords[pos + 1] = (coords[pos + 1] * z) + lastY;
}
}
mMapGenerator.renderWay((byte) layer, tags, coords, index, true);
mMapGenerator.renderWay((byte) layer, tags, coords, index, polygon);
return true;
}
private boolean decodeTileNodes() throws IOException {
int bytes = decodeVarint32();
Log.d(TAG, "way nodes " + bytes);
// Log.d(TAG, "decode nodes " + bytes);
int end = bytesRead + bytes;
int tagCnt = 0;
int coordCnt = 0;
byte layer = 0;
Tag[] tags = null;
while (bytesRead < end) {
// read tag and wire type
int val = decodeVarint32();
if (val == 0)
break;
int tag = (val >> 3);
// int wireType = val & 7;
// Log.d(TAG, "way " + tag + " " + wireType + " bytes:" + bytes);
int cnt;
switch (tag) {
case TAG_NODE_TAGS:
tags = decodeWayTags(tagCnt);
break;
case TAG_NODE_COORDS:
cnt = decodeNodeCoordinates(coordCnt, layer, tags);
if (cnt != coordCnt) {
Log.d(TAG, "EEEK wrong number of coordintes");
return false;
}
break;
case TAG_NODE_LAYER:
layer = (byte) decodeVarint32();
break;
case TAG_NODE_NUM_TAGS:
tagCnt = decodeVarint32();
break;
case TAG_NODE_NUM_COORDS:
coordCnt = decodeVarint32();
break;
default:
Log.d(TAG, "invalid type for node: " + tag);
}
}
return true;
}
private int decodeNodeCoordinates(int numNodes, byte layer, Tag[] tags)
throws IOException {
int bytes = decodeVarint32();
readBuffer(bytes);
int cnt = 0;
int end = bufferPos + bytes;
// read repeated sint32
while (bufferPos < end && cnt < numNodes) {
float lon = decodeZigZag32(decodeVarint32()) * mScaleFactor;
float lat = decodeZigZag32(decodeVarint32()) * mScaleFactor;
mMapGenerator.renderPointOfInterest(layer, lat, lon, tags);
cnt += 2;
}
return cnt;
}
private int MAX_WAY_COORDS = 32768;
private int MAX_WAY_INDICES = 1000;
private int[] tmpTags = new int[32];
private int[] tmpIndices = new int[MAX_WAY_INDICES];
private float[] tmpCoords = new float[MAX_WAY_COORDS];
// private boolean ensureBufferSize(int size) throws IOException {
@ -358,47 +449,62 @@ public class MapDatabase implements IMapDatabase {
// return true;
// }
private int decodeWayTags() throws IOException {
private Tag[] decodeWayTags(int tagCnt) throws IOException {
int bytes = decodeVarint32();
// Log.d(TAG, "way tags: " + bytes);
Tag[] tags = new Tag[tagCnt];
int cnt = 0;
int end = bytesRead + bytes;
int max = curTags.length;
while (bytesRead < end)
tmpTags[cnt++] = decodeVarint32();
while (bytesRead < end) {
int tagNum = decodeVarint32();
return cnt;
if (tagNum < 0 || cnt == tagCnt)
continue;
if (tagNum < Tags.MAX)
tags[cnt++] = Tags.tags[tagNum];
else {
tagNum -= Tags.LIMIT;
if (tagNum >= 0 && tagNum < max) {
// Log.d(TAG, "variable tag: " + curTags[tagNum]);
tags[cnt++] = curTags[tagNum];
}
}
// else DEBUG...
}
return tags;
}
private int decodeWayIndices() throws IOException {
private short[] decodeWayIndices(int indexCnt) throws IOException {
int bytes = decodeVarint32();
// Log.d(TAG, "way indices: " + bytes);
short[] index = new short[indexCnt];
int cnt = 0;
int end = bytesRead + bytes;
while (bytesRead < end) {
int val = decodeVarint32();
if (cnt >= MAX_WAY_INDICES) {
MAX_WAY_INDICES += 128;
Log.d(TAG, "increase indices array " + MAX_WAY_INDICES);
int[] tmp = new int[MAX_WAY_INDICES];
System.arraycopy(tmpIndices, 0, tmp, 0, cnt);
tmpIndices = tmp;
}
tmpIndices[cnt++] = val;
if (cnt < indexCnt)
index[cnt++] = (short) (val * 2);
// else DEBUG...
}
return cnt;
return index;
}
private int decodeWayCoordinates() throws IOException {
private int decodeWayCoordinates(boolean skip) throws IOException {
int bytes = decodeVarint32();
readBuffer(bytes);
if (skip) {
bufferPos += bytes;
return 0;
}
int pos = bufferPos;
int end = pos + bytes;
@ -511,7 +617,18 @@ public class MapDatabase implements IMapDatabase {
buffer[bufferSize - 1] = 0; // FIXME is this needed?
break;
}
bufferSize += len;
// if (len == 0)
// try {
// wait(50);
// } catch (InterruptedException e) {
// // just waiting for data
// }
if (mCanceled)
throw new IOException("... canceld?");
}
// Log.d(TAG, "needed " + size + " pos " + bufferPos + ", size "
@ -614,8 +731,12 @@ public class MapDatabase implements IMapDatabase {
@Override
public void cancel() {
mCanceled = true;
mClient.getConnectionManager().shutdown();
mClient = null;
if (mRequest != null) {
mRequest.abort();
mRequest = null;
}
// mClient.getConnectionManager().shutdown();
// mClient = null;
}
}

View File

@ -0,0 +1,958 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.database.pbmap;
import org.mapsforge.core.Tag;
public class Tags {
public final static int MAX = 654;
public final static int LIMIT = 1024;
private static final String s_limited = "limited".intern();
private static final String s_chain = "chain".intern();
private static final String s_viaduct = "viaduct".intern();
private static final String s_department_store = "department_store".intern();
private static final String s_factory = "factory".intern();
private static final String s_recreation_ground = "recreation_ground".intern();
private static final String s_nature_reserve = "nature_reserve".intern();
private static final String s_apartment = "apartment".intern();
private static final String s_preserved = "preserved".intern();
private static final String s_stationery = "stationery".intern();
private static final String s_gravel = "gravel".intern();
private static final String s_hill = "hill".intern();
private static final String s_water_well = "water_well".intern();
private static final String s_garden = "garden".intern();
private static final String s_permissive = "permissive".intern();
private static final String s_deli = "deli".intern();
private static final String s_industrial_retail = "industrial;retail".intern();
private static final String s_city_wall = "city_wall".intern();
private static final String s_artwork = "artwork".intern();
private static final String s_chapel = "chapel".intern();
private static final String s_school = "school".intern();
private static final String s_caravan_site = "caravan_site".intern();
private static final String s_reservoir_watershed = "reservoir_watershed".intern();
private static final String s_local_authority = "local_authority".intern();
private static final String s_miniature_golf = "miniature_golf".intern();
private static final String s_bus_stop = "bus_stop".intern();
private static final String s_convenience = "convenience".intern();
private static final String s_kissing_gate = "kissing_gate".intern();
private static final String s_subway = "subway".intern();
private static final String s_cutline = "cutline".intern();
private static final String s_disused = "disused".intern();
private static final String s_clothes = "clothes".intern();
private static final String s_bicycle = "bicycle".intern();
private static final String s_meadow = "meadow".intern();
private static final String s_fence = "fence".intern();
private static final String s_video = "video".intern();
private static final String s_monorail = "monorail".intern();
private static final String s_clock = "clock".intern();
private static final String s_dirt = "dirt".intern();
private static final String s_border_control = "border_control".intern();
private static final String s_access = "access".intern();
private static final String s_public = "public".intern();
private static final String s_fast_food = "fast_food".intern();
private static final String s_transportation = "transportation".intern();
private static final String s_commercial = "commercial".intern();
private static final String s_water = "water".intern();
private static final String s_beacon = "beacon".intern();
private static final String s_trunk = "trunk".intern();
private static final String s_path = "path".intern();
private static final String s_bicycle_rental = "bicycle_rental".intern();
private static final String s_miniature = "miniature".intern();
private static final String s_car_parts = "car_parts".intern();
private static final String s_light_rail = "light_rail".intern();
private static final String s_military = "military".intern();
private static final String s_bog = "bog".intern();
private static final String s_hiking = "hiking".intern();
private static final String s_lift_gate = "lift_gate".intern();
private static final String s_private = "private".intern();
private static final String s_county = "county".intern();
private static final String s_secondary_link = "secondary_link".intern();
private static final String s_marker = "marker".intern();
private static final String s_islet = "islet".intern();
private static final String s_holding_position = "holding_position".intern();
private static final String s_tertiary = "tertiary".intern();
private static final String s_water_park = "water_park".intern();
private static final String s_stream = "stream".intern();
private static final String s_hospital = "hospital".intern();
private static final String s_destination = "destination".intern();
private static final String s_MDF = "MDF".intern();
private static final String s_sports = "sports".intern();
private static final String s_vineyard = "vineyard".intern();
private static final String s_music = "music".intern();
private static final String s_6 = "6".intern();
private static final String s_entrance = "entrance".intern();
private static final String s_beauty = "beauty".intern();
private static final String s_give_way = "give_way".intern();
private static final String s_kiosk = "kiosk".intern();
private static final String s_stone = "stone".intern();
private static final String s_grass_paver = "grass_paver".intern();
private static final String s_deciduous = "deciduous".intern();
private static final String s_train = "train".intern();
private static final String s_organic = "organic".intern();
private static final String s_farmyard = "farmyard".intern();
private static final String s_riverbank = "riverbank".intern();
private static final String s_doityourself = "doityourself".intern();
private static final String s_town = "town".intern();
private static final String s_dog_park = "dog_park".intern();
private static final String s_village_green = "village_green".intern();
private static final String s_tunnel = "tunnel".intern();
private static final String s_car = "car".intern();
private static final String s_roof = "roof".intern();
private static final String s_mall = "mall".intern();
private static final String s_ferry_terminal = "ferry_terminal".intern();
private static final String s_cave_entrance = "cave_entrance".intern();
private static final String s_detached = "detached".intern();
private static final String s_concrete_plates = "concrete:plates".intern();
private static final String s_public_building = "public_building".intern();
private static final String s_buffer_stop = "buffer_stop".intern();
private static final String s_lock = "lock".intern();
private static final String s_dolphin = "dolphin".intern();
private static final String s_taxiway = "taxiway".intern();
private static final String s_hunting_stand = "hunting_stand".intern();
private static final String s_estate_agent = "estate_agent".intern();
private static final String s_station = "station".intern();
private static final String s_car_repair = "car_repair".intern();
private static final String s_dyke = "dyke".intern();
private static final String s_hangar = "hangar".intern();
private static final String s_information = "information".intern();
private static final String s_1 = "1".intern();
private static final String s_forest = "forest".intern();
private static final String s_gate = "gate".intern();
private static final String s_beach = "beach".intern();
private static final String s_laundry = "laundry".intern();
private static final String s_speed_camera = "speed_camera".intern();
private static final String s_staircase = "staircase".intern();
private static final String s_farm = "farm".intern();
private static final String s_stop = "stop".intern();
private static final String s_bump_gate = "bump_gate".intern();
private static final String s_motorway = "motorway".intern();
private static final String s_water_tower = "water_tower".intern();
private static final String s_abutters = "abutters".intern();
private static final String s_driving_school = "driving_school".intern();
private static final String s_natural = "natural".intern();
private static final String s_orchard = "orchard".intern();
private static final String s_wheelchair = "wheelchair".intern();
private static final String s_swimming_pool = "swimming_pool".intern();
private static final String s_switch = "switch".intern();
private static final String s_block = "block".intern();
private static final String s_turnstile = "turnstile".intern();
private static final String s_camp_site = "camp_site".intern();
private static final String s_shoes = "shoes".intern();
private static final String s_reservoir = "reservoir".intern();
private static final String s_pebblestone = "pebblestone".intern();
private static final String s_stile = "stile".intern();
private static final String s_embassy = "embassy".intern();
private static final String s_postal_code = "postal_code".intern();
private static final String s_retaining_wall = "retaining_wall".intern();
private static final String s_bridleway = "bridleway".intern();
private static final String s_pitch = "pitch".intern();
private static final String s_agricultural = "agricultural".intern();
private static final String s_post_office = "post_office".intern();
private static final String s_parking_fuel = "parking;fuel".intern();
private static final String s_bureau_de_change = "bureau_de_change".intern();
private static final String s_mini_roundabout = "mini_roundabout".intern();
private static final String s_hov = "hov".intern();
private static final String s_police = "police".intern();
private static final String s_courthouse = "courthouse".intern();
private static final String s_raceway = "raceway".intern();
private static final String s_kindergarten = "kindergarten".intern();
private static final String s_attraction = "attraction".intern();
private static final String s_marsh = "marsh".intern();
private static final String s_reservoir_covered = "reservoir_covered".intern();
private static final String s_petroleum_well = "petroleum_well".intern();
private static final String s_silo = "silo".intern();
private static final String s_toys = "toys".intern();
private static final String s_apron = "apron".intern();
private static final String s_halt = "halt".intern();
private static final String s_dam = "dam".intern();
private static final String s_golf_course = "golf_course".intern();
private static final String s_detour = "detour".intern();
private static final String s_tree_row = "tree_row".intern();
private static final String s_copyshop = "copyshop".intern();
private static final String s_milestone = "milestone".intern();
private static final String s_foot = "foot".intern();
private static final String s_tourism = "tourism".intern();
private static final String s_bank = "bank".intern();
private static final String s_dry_cleaning = "dry_cleaning".intern();
private static final String s_tram = "tram".intern();
private static final String s_trolleybus = "trolleybus".intern();
private static final String s_university = "university".intern();
private static final String s_hampshire_gate = "hampshire_gate".intern();
private static final String s_embankment = "embankment".intern();
private static final String s_rock = "rock".intern();
private static final String s_crossing = "crossing".intern();
private static final String s_volcano = "volcano".intern();
private static final String s_greengrocer = "greengrocer".intern();
private static final String s_kerb = "kerb".intern();
private static final String s_waste_disposal = "waste_disposal".intern();
private static final String s_grave_yard = "grave_yard".intern();
private static final String s_coniferous = "coniferous".intern();
private static final String s_house = "house".intern();
private static final String s_books = "books".intern();
private static final String s_neighbourhood = "neighbourhood".intern();
private static final String s_hostel = "hostel".intern();
private static final String s_alcohol = "alcohol".intern();
private static final String s_restricted = "restricted".intern();
private static final String s_motel = "motel".intern();
private static final String s_sand = "sand".intern();
private static final String s_fishmonger = "fishmonger".intern();
private static final String s_fountain = "fountain".intern();
private static final String s_playground = "playground".intern();
private static final String s_7 = "7".intern();
private static final String s_parking_aisle = "parking_aisle".intern();
private static final String s_protected_area = "protected_area".intern();
private static final String s_electronics = "electronics".intern();
private static final String s_Paved = "Paved".intern();
private static final String s_highway = "highway".intern();
private static final String s_fine_gravel = "fine_gravel".intern();
private static final String s_barrier = "barrier".intern();
private static final String s_hairdresser = "hairdresser".intern();
private static final String s_post_box = "post_box".intern();
private static final String s_pub = "pub".intern();
private static final String s_coastline = "coastline".intern();
private static final String s_marina = "marina".intern();
private static final String s_reedbed = "reedbed".intern();
private static final String s_biergarten = "biergarten".intern();
private static final String s_dismantled = "dismantled".intern();
private static final String s_farmland = "farmland".intern();
private static final String s_yard = "yard".intern();
private static final String s_route = "route".intern();
private static final String s_atm = "atm".intern();
private static final String s_place = "place".intern();
private static final String s_bus_station = "bus_station".intern();
private static final String s_retail = "retail".intern();
private static final String s_industrial = "industrial".intern();
private static final String s_municipality = "municipality".intern();
private static final String s_primary = "primary".intern();
private static final String s_nursing_home = "nursing_home".intern();
private static final String s_florist = "florist".intern();
private static final String s_ditch = "ditch".intern();
private static final String s_national_park = "national_park".intern();
private static final String s_city = "city".intern();
private static final String s_confectionery = "confectionery".intern();
private static final String s_service = "service".intern();
private static final String s_unknown = "unknown".intern();
private static final String s_cycle_barrier = "cycle_barrier".intern();
private static final String s_elevator = "elevator".intern();
private static final String s_2 = "2".intern();
private static final String s_car_rental = "car_rental".intern();
private static final String s_flagpole = "flagpole".intern();
private static final String s_cabin = "cabin".intern();
private static final String s_paved = "paved".intern();
private static final String s_guest_house = "guest_house".intern();
private static final String s_mobile_phone = "mobile_phone".intern();
private static final String s_lot = "lot".intern();
private static final String s_quarry = "quarry".intern();
private static final String s_train_station = "train_station".intern();
private static final String s_hotel = "hotel".intern();
private static final String s_park = "park".intern();
private static final String s_hut = "hut".intern();
private static final String s_dentist = "dentist".intern();
private static final String s_doctors = "doctors".intern();
private static final String s_greenhouse = "greenhouse".intern();
private static final String s_11 = "11".intern();
private static final String s_10 = "10".intern();
private static final String s_theme_park = "theme_park".intern();
private static final String s_tree = "tree".intern();
private static final String s_shower = "shower".intern();
private static final String s_siding = "siding".intern();
private static final String s_aeroway = "aeroway".intern();
private static final String s_emergency_access_point = "emergency_access_point"
.intern();
private static final String s_watermill = "watermill".intern();
private static final String s_college = "college".intern();
private static final String s_landuse = "landuse".intern();
private static final String s_tracktype = "tracktype".intern();
private static final String s_ferry = "ferry".intern();
private static final String s_bridge = "bridge".intern();
private static final String s_vacant = "vacant".intern();
private static final String s_cattle_grid = "cattle_grid".intern();
private static final String s_brownfield = "brownfield".intern();
private static final String s_allotments = "allotments".intern();
private static final String s_alley = "alley".intern();
private static final String s_pedestrian = "pedestrian".intern();
private static final String s_borough = "borough".intern();
private static final String s_bare_rock = "bare_rock".intern();
private static final String s_motorcycle = "motorcycle".intern();
private static final String s_bakery = "bakery".intern();
private static final String s_zoo = "zoo".intern();
private static final String s_scree = "scree".intern();
private static final String s_fire_station = "fire_station".intern();
private static final String s_theatre = "theatre".intern();
private static final String s_track = "track".intern();
private static final String s_reinforced_slope = "reinforced_slope".intern();
private static final String s_slipway = "slipway".intern();
private static final String s_mangrove = "mangrove".intern();
private static final String s_aerodrome = "aerodrome".intern();
private static final String s_byway = "byway".intern();
private static final String s_metal = "metal".intern();
private static final String s_swamp = "swamp".intern();
private static final String s_construction = "construction".intern();
private static final String s_grassland = "grassland".intern();
private static final String s_shop = "shop".intern();
private static final String s_soakhole = "soakhole".intern();
private static final String s_asphalt = "asphalt".intern();
private static final String s_social_facility = "social_facility".intern();
private static final String s_isolated_dwelling = "isolated_dwelling".intern();
private static final String s_hamlet = "hamlet".intern();
private static final String s_picnic_table = "picnic_table".intern();
private static final String s_artificial = "artificial".intern();
private static final String s_earth = "earth".intern();
private static final String s_grit_bin = "grit_bin".intern();
private static final String s_ground = "ground".intern();
private static final String s_groyne = "groyne".intern();
private static final String s_office = "office".intern();
private static final String s_state = "state".intern();
private static final String s_terminal = "terminal".intern();
private static final String s_wood = "wood".intern();
private static final String s_fuel = "fuel".intern();
private static final String s_8 = "8".intern();
private static final String s_garden_centre = "garden_centre".intern();
private static final String s_horse_riding = "horse_riding".intern();
private static final String s_viewpoint = "viewpoint".intern();
private static final String s_designated = "designated".intern();
private static final String s_leisure = "leisure".intern();
private static final String s_waste_basket = "waste_basket".intern();
private static final String s_hifi = "hifi".intern();
private static final String s_hedge = "hedge".intern();
private static final String s_spur = "spur".intern();
private static final String s_chimney = "chimney".intern();
private static final String s_secondary = "secondary".intern();
private static final String s_rest_area = "rest_area".intern();
private static final String s_bar = "bar".intern();
private static final String s_bay = "bay".intern();
private static final String s_common = "common".intern();
private static final String s_river = "river".intern();
private static final String s_ruins = "ruins".intern();
private static final String s_terrace = "terrace".intern();
private static final String s_art = "art".intern();
private static final String s_residental = "residental".intern();
private static final String s_newsagent = "newsagent".intern();
private static final String s_turntable = "turntable".intern();
private static final String s_computer = "computer".intern();
private static final String s_wetland = "wetland".intern();
private static final String s_driveway = "driveway".intern();
private static final String s_parking = "parking".intern();
private static final String s_compacted = "compacted".intern();
private static final String s_barn = "barn".intern();
private static final String s_alpine_hut = "alpine_hut".intern();
private static final String s_wire_fence = "wire_fence".intern();
private static final String s_unpaved = "unpaved".intern();
private static final String s_dormitory = "dormitory".intern();
private static final String s_mud = "mud".intern();
private static final String s_3 = "3".intern();
private static final String s_semi = "semi".intern();
private static final String s_boundary = "boundary".intern();
private static final String s_field_boundary = "field_boundary".intern();
private static final String s_beverages = "beverages".intern();
private static final String s_supermarket = "supermarket".intern();
private static final String s_store = "store".intern();
private static final String s_restaurant = "restaurant".intern();
private static final String s_region = "region".intern();
private static final String s_variety_store = "variety_store".intern();
private static final String s_saltmarsh = "saltmarsh".intern();
private static final String s_landform = "landform".intern();
private static final String s_helipad = "helipad".intern();
private static final String s_railway = "railway".intern();
private static final String s_greenhouse_horticulture = "greenhouse_horticulture"
.intern();
private static final String s_wall = "wall".intern();
private static final String s_recycling = "recycling".intern();
private static final String s_passing_place = "passing_place".intern();
private static final String s_church = "church".intern();
private static final String s_pharmacy = "pharmacy".intern();
private static final String s_lighthouse = "lighthouse".intern();
private static final String s_platform = "platform".intern();
private static final String s_cinema = "cinema".intern();
private static final String s_political = "political".intern();
private static final String s_stadium = "stadium".intern();
private static final String s_basin = "basin".intern();
private static final String s_gasometer = "gasometer".intern();
private static final String s_bicycle_parking = "bicycle_parking".intern();
private static final String s_bbq = "bbq".intern();
private static final String s_incline_steep = "incline_steep".intern();
private static final String s_drinking_water = "drinking_water".intern();
private static final String s_living_street = "living_street".intern();
private static final String s_chalet = "chalet".intern();
private static final String s_narrow_gauge = "narrow_gauge".intern();
private static final String s_prison = "prison".intern();
private static final String s_mine = "mine".intern();
private static final String s_level_crossing = "level_crossing".intern();
private static final String s_water_works = "water_works".intern();
private static final String s_street_lamp = "street_lamp".intern();
private static final String s_main = "main".intern();
private static final String s_tank = "tank".intern();
private static final String s_abandoned = "abandoned".intern();
private static final String s_ski = "ski".intern();
private static final String s_runway = "runway".intern();
private static final String s_parking_space = "parking_space".intern();
private static final String s_dirt_sand = "dirt/sand".intern();
private static final String s_salt_pond = "salt_pond".intern();
private static final String s_hedge_bank = "hedge_bank".intern();
private static final String s_amenity = "amenity".intern();
private static final String s_telephone = "telephone".intern();
private static final String s_surface = "surface".intern();
private static final String s_travel_agency = "travel_agency".intern();
private static final String s_hardware = "hardware".intern();
private static final String s_wastewater_plant = "wastewater_plant".intern();
private static final String s_waterway = "waterway".intern();
private static final String s_butcher = "butcher".intern();
private static final String s_surveillance = "surveillance".intern();
private static final String s_Dirt_Sand = "Dirt/Sand".intern();
private static final String s_9 = "9".intern();
private static final String s_windmill = "windmill".intern();
private static final String s_picnic_site = "picnic_site".intern();
private static final String s_rail = "rail".intern();
private static final String s_cement = "cement".intern();
private static final String s_sauna = "sauna".intern();
private static final String s_suburb = "suburb".intern();
private static final String s_waterfall = "waterfall".intern();
private static final String s_bunker = "bunker".intern();
private static final String s_ice_cream = "ice_cream".intern();
private static final String s_culvert = "culvert".intern();
private static final String s_drain = "drain".intern();
private static final String s_dock = "dock".intern();
private static final String s_glasshouse = "glasshouse".intern();
private static final String s_no = "no".intern();
private static final String s_well = "well".intern();
private static final String s_wet_meadow = "wet_meadow".intern();
private static final String s_concrete = "concrete".intern();
private static final String s_dismount = "dismount".intern();
private static final String s_vending_machine = "vending_machine".intern();
private static final String s_oneway = "oneway".intern();
private static final String s_taxi = "taxi".intern();
private static final String s_outdoor = "outdoor".intern();
private static final String s_proposed = "proposed".intern();
private static final String s_sally_port = "sally_port".intern();
private static final String s_photo = "photo".intern();
private static final String s_plant_nursery = "plant_nursery".intern();
private static final String s_clinic = "clinic".intern();
private static final String s_fishing = "fishing".intern();
private static final String s_yes = "yes".intern();
private static final String s_turning_circle = "turning_circle".intern();
private static final String s_toilets = "toilets".intern();
private static final String s_guard_rail = "guard_rail".intern();
private static final String s_townhall = "townhall".intern();
private static final String s_community_centre = "community_centre".intern();
private static final String s_residential = "residential".intern();
private static final String s_cemetery = "cemetery".intern();
private static final String s_survey_point = "survey_point".intern();
private static final String s_bench = "bench".intern();
private static final String s_4 = "4".intern();
private static final String s_bollard = "bollard".intern();
private static final String s_sports_centre = "sports_centre".intern();
private static final String s_paving_stones_30 = "paving_stones:30".intern();
private static final String s_administrative = "administrative".intern();
private static final String s_Building = "Building".intern();
private static final String s_customers = "customers".intern();
private static final String s_emergency = "emergency".intern();
private static final String s_motorway_junction = "motorway_junction".intern();
private static final String s_grade1 = "grade1".intern();
private static final String s_grade3 = "grade3".intern();
private static final String s_grade2 = "grade2".intern();
private static final String s_grade5 = "grade5".intern();
private static final String s_grade4 = "grade4".intern();
private static final String s_lock_gate = "lock_gate".intern();
private static final String s_furniture = "furniture".intern();
private static final String s_place_of_worship = "place_of_worship".intern();
private static final String s_optician = "optician".intern();
private static final String s_gift = "gift".intern();
private static final String s_parking_entrance = "parking_entrance".intern();
private static final String s_garage = "garage".intern();
private static final String s_tram_stop = "tram_stop".intern();
private static final String s_steps = "steps".intern();
private static final String s_tower = "tower".intern();
private static final String s_works = "works".intern();
private static final String s_shed = "shed".intern();
private static final String s_car_sharing = "car_sharing".intern();
private static final String s_apartments = "apartments".intern();
private static final String s_spring = "spring".intern();
private static final String s_village = "village".intern();
private static final String s_library = "library".intern();
private static final String s_emergency_access = "emergency_access".intern();
private static final String s_home = "home".intern();
private static final String s_farm_auxiliary = "farm_auxiliary".intern();
private static final String s_primary_link = "primary_link".intern();
private static final String s_toll_booth = "toll_booth".intern();
private static final String s_jewelry = "jewelry".intern();
private static final String s_pet = "pet".intern();
private static final String s_veterinary = "veterinary".intern();
private static final String s_man_made = "man_made".intern();
private static final String s_motorway_link = "motorway_link".intern();
private static final String s_offices = "offices".intern();
private static final String s_power = "power".intern();
private static final String s_weir = "weir".intern();
private static final String s_unsurfaced = "unsurfaced".intern();
private static final String s_tertiary_link = "tertiary_link".intern();
private static final String s_trunk_link = "trunk_link".intern();
private static final String s_tyres = "tyres".intern();
private static final String s_paving_stones = "paving_stones".intern();
private static final String s_pipeline = "pipeline".intern();
private static final String s_census = "census".intern();
private static final String s_incline = "incline".intern();
private static final String s_footway = "footway".intern();
private static final String s_drive_through = "drive-through".intern();
private static final String s_island = "island".intern();
private static final String s_monitoring_station = "monitoring_station".intern();
private static final String s_nightclub = "nightclub".intern();
private static final String s_unclassified = "unclassified".intern();
private static final String s_aquaculture = "aquaculture".intern();
private static final String s_mixed = "mixed".intern();
private static final String s_road = "road".intern();
private static final String s_greenfield = "greenfield".intern();
private static final String s_breakwater = "breakwater".intern();
private static final String s_services = "services".intern();
private static final String s_railway_crossing = "railway_crossing".intern();
private static final String s_residentiel1 = "residentiel1".intern();
private static final String s_canal = "canal".intern();
private static final String s__1 = "-1".intern();
private static final String s_ridge = "ridge".intern();
private static final String s_fabric = "fabric".intern();
private static final String s_museum = "museum".intern();
private static final String s_communications_tower = "communications_tower".intern();
private static final String s_semi_detached = "semi-detached".intern();
private static final String s_conservation = "conservation".intern();
private static final String s_way = "way".intern();
private static final String s_wood_fence = "wood_fence".intern();
private static final String s_manufacture = "manufacture".intern();
private static final String s_admin_level = "admin_level".intern();
private static final String s_building_concrete = "building_concrete".intern();
private static final String s_bus = "bus".intern();
private static final String s_collapsed = "collapsed".intern();
private static final String s_ford = "ford".intern();
private static final String s_delivery = "delivery".intern();
private static final String s_garages = "garages".intern();
private static final String s_funeral_directors = "funeral_directors".intern();
private static final String s_land = "land".intern();
private static final String s_interlock = "interlock".intern();
private static final String s_reef = "reef".intern();
private static final String s_crane = "crane".intern();
private static final String s_true = "true".intern();
private static final String s_storage_tank = "storage_tank".intern();
private static final String s_official = "official".intern();
private static final String s_subway_entrance = "subway_entrance".intern();
private static final String s_mtb = "mtb".intern();
private static final String s_grass = "grass".intern();
private static final String s_marketplace = "marketplace".intern();
private static final String s_rapids = "rapids".intern();
private static final String s_car_wash = "car_wash".intern();
private static final String s_general = "general".intern();
private static final String s_cafe = "cafe".intern();
private static final String s_locality = "locality".intern();
private static final String s_glacier = "glacier".intern();
private static final String s_storage = "storage".intern();
private static final String s_cycleway = "cycleway".intern();
private static final String s_forestry = "forestry".intern();
private static final String s_field = "field".intern();
private static final String s_5 = "5".intern();
private static final String s_arts_centre = "arts_centre".intern();
private static final String s_warehouse = "warehouse".intern();
private static final String s_chemist = "chemist".intern();
private static final String s_pier = "pier".intern();
private static final String s_scrub = "scrub".intern();
private static final String s_shelter = "shelter".intern();
private static final String s_emergency_phone = "emergency_phone".intern();
private static final String s_tidalflat = "tidalflat".intern();
private static final String s_cobblestone = "cobblestone".intern();
private static final String s_fell = "fell".intern();
private static final String s_peak = "peak".intern();
private static final String s_charging_station = "charging_station".intern();
private static final String s_cliff = "cliff".intern();
private static final String s_building = "building".intern();
private static final String s_fire_hydrant = "fire_hydrant".intern();
private static final String s_traffic_signals = "traffic_signals".intern();
private static final String s_heath = "heath".intern();
private static final String s_landfill = "landfill".intern();
private static final String s_mast = "mast".intern();
private static final String s_boutique = "boutique".intern();
private static final String s_boat_storage = "boat_storage".intern();
public final static Tag[] tags = {
new Tag(s_building, s_yes, true), new Tag(s_highway, s_residential, true),
new Tag(s_highway, s_service, true), new Tag(s_waterway, s_stream, true),
new Tag(s_highway, s_unclassified, true), new Tag(s_highway, s_track, true),
new Tag(s_oneway, s_yes, true), new Tag(s_natural, s_water, true),
new Tag(s_highway, s_footway, true), new Tag(s_access, s_private, true),
new Tag(s_highway, s_tertiary, true), new Tag(s_highway, s_path, true),
new Tag(s_highway, s_secondary, true), new Tag(s_landuse, s_forest, true),
new Tag(s_bridge, s_yes, true), new Tag(s_natural, s_tree, true),
new Tag(s_surface, s_paved, true), new Tag(s_natural, s_wood, true),
new Tag(s_highway, s_primary, true), new Tag(s_landuse, s_grass, true),
new Tag(s_landuse, s_residential, true), new Tag(s_surface, s_unpaved, true),
new Tag(s_highway, s_bus_stop, true), new Tag(s_surface, s_asphalt, true),
new Tag(s_bicycle, s_yes, true), new Tag(s_amenity, s_parking, true),
new Tag(s_place, s_locality, true), new Tag(s_railway, s_rail, true),
new Tag(s_service, s_parking_aisle, true),
new Tag(s_boundary, s_administrative, true),
new Tag(s_building, s_house, true), new Tag(s_place, s_village, true),
new Tag(s_natural, s_coastline, true), new Tag(s_tracktype, s_grade2, true),
new Tag(s_oneway, s_no, true), new Tag(s_service, s_driveway, true),
new Tag(s_highway, s_turning_circle, true), new Tag(s_place, s_hamlet, true),
new Tag(s_natural, s_wetland, true), new Tag(s_tracktype, s_grade3, true),
new Tag(s_waterway, s_river, true), new Tag(s_highway, s_cycleway, true),
new Tag(s_barrier, s_fence, true), new Tag(s_building, s_residential, true),
new Tag(s_amenity, s_school, true), new Tag(s_highway, s_crossing, true),
new Tag(s_admin_level, s_8, true), new Tag(s_highway, s_trunk, true),
new Tag(s_amenity, s_place_of_worship, true),
new Tag(s_landuse, s_farmland, true), new Tag(s_tracktype, s_grade1, true),
new Tag(s_highway, s_road, true), new Tag(s_landuse, s_farm, true),
new Tag(s_surface, s_gravel, true), new Tag(s_landuse, s_meadow, true),
new Tag(s_highway, s_motorway, true),
new Tag(s_highway, s_traffic_signals, true),
new Tag(s_building, s_hut, true), new Tag(s_highway, s_motorway_link, true),
new Tag(s_tracktype, s_grade4, true), new Tag(s_barrier, s_gate, true),
new Tag(s_highway, s_living_street, true), new Tag(s_bicycle, s_no, true),
new Tag(s_leisure, s_pitch, true), new Tag(s_tunnel, s_yes, true),
new Tag(s_surface, s_ground, true), new Tag(s_highway, s_steps, true),
new Tag(s_natural, s_land, true), new Tag(s_man_made, s_survey_point, true),
new Tag(s_tracktype, s_grade5, true), new Tag(s_waterway, s_ditch, true),
new Tag(s_leisure, s_park, true), new Tag(s_amenity, s_restaurant, true),
new Tag(s_barrier, s_wall, true), new Tag(s_waterway, s_riverbank, true),
new Tag(s_amenity, s_bench, true), new Tag(s_building, s_garage, true),
new Tag(s_natural, s_scrub, true), new Tag(s_highway, s_pedestrian, true),
new Tag(s_natural, s_peak, true), new Tag(s_building, s_entrance, true),
new Tag(s_landuse, s_reservoir, true), new Tag(s_access, s_yes, true),
new Tag(s_bicycle, s_designated, true),
new Tag(s_leisure, s_swimming_pool, true),
new Tag(s_landuse, s_farmyard, true),
new Tag(s_railway, s_level_crossing, true),
new Tag(s_building, s_apartments, true), new Tag(s_surface, s_grass, true),
new Tag(s_wheelchair, s_yes, true), new Tag(s_service, s_alley, true),
new Tag(s_landuse, s_industrial, true), new Tag(s_amenity, s_fuel, true),
new Tag(s_surface, s_dirt, true), new Tag(s_highway, s_trunk_link, true),
new Tag(s_waterway, s_drain, true), new Tag(s_barrier, s_hedge, true),
new Tag(s_amenity, s_grave_yard, true),
new Tag(s_tourism, s_information, true),
new Tag(s_shop, s_supermarket, true),
new Tag(s_highway, s_primary_link, true), new Tag(s_wood, s_deciduous, true),
new Tag(s_leisure, s_playground, true), new Tag(s_building, s_roof, true),
new Tag(s_building, s_industrial, true),
new Tag(s_amenity, s_post_box, true), new Tag(s_waterway, s_canal, true),
new Tag(s_barrier, s_bollard, true), new Tag(s_leisure, s_garden, true),
new Tag(s_wood, s_mixed, true), new Tag(s_landuse, s_cemetery, true),
new Tag(s_landuse, s_orchard, true), new Tag(s_shop, s_convenience, true),
new Tag(s_access, s_permissive, true), new Tag(s_surface, s_concrete, true),
new Tag(s_surface, s_paving_stones, true), new Tag(s_service, s_spur, true),
new Tag(s_building, s_garages, true), new Tag(s_amenity, s_bank, true),
new Tag(s_tourism, s_hotel, true), new Tag(s_access, s_no, true),
new Tag(s_amenity, s_fast_food, true), new Tag(s_man_made, s_pier, true),
new Tag(s_amenity, s_kindergarten, true),
new Tag(s_access, s_agricultural, true),
new Tag(s_surface, s_cobblestone, true), new Tag(s_wheelchair, s_no, true),
new Tag(s_amenity, s_cafe, true), new Tag(s_amenity, s_hospital, true),
new Tag(s_amenity, s_post_office, true),
new Tag(s_amenity, s_public_building, true),
new Tag(s_amenity, s_recycling, true),
new Tag(s_highway, s_street_lamp, true), new Tag(s_man_made, s_tower, true),
new Tag(s_waterway, s_dam, true), new Tag(s_amenity, s_pub, true),
new Tag(s_wood, s_coniferous, true), new Tag(s_access, s_destination, true),
new Tag(s_admin_level, s_6, true), new Tag(s_landuse, s_commercial, true),
new Tag(s_amenity, s_pharmacy, true), new Tag(s_railway, s_abandoned, true),
new Tag(s_service, s_yard, true), new Tag(s_place, s_island, true),
new Tag(s_oneway, s__1, true), new Tag(s_landuse, s_quarry, true),
new Tag(s_landuse, s_vineyard, true),
new Tag(s_highway, s_motorway_junction, true),
new Tag(s_railway, s_station, true), new Tag(s_landuse, s_allotments, true),
new Tag(s_barrier, s_lift_gate, true), new Tag(s_admin_level, s_10, true),
new Tag(s_amenity, s_telephone, true), new Tag(s_place, s_town, true),
new Tag(s_man_made, s_cutline, true), new Tag(s_place, s_suburb, true),
new Tag(s_aeroway, s_taxiway, true), new Tag(s_wheelchair, s_limited, true),
new Tag(s_highway, s_secondary_link, true),
new Tag(s_leisure, s_sports_centre, true),
new Tag(s_amenity, s_bicycle_parking, true),
new Tag(s_surface, s_sand, true), new Tag(s_highway, s_stop, true),
new Tag(s_man_made, s_works, true), new Tag(s_landuse, s_retail, true),
new Tag(s_amenity, s_fire_station, true), new Tag(s_service, s_siding, true),
new Tag(s_amenity, s_toilets, true), new Tag(s_bench, s_yes, true),
new Tag(s_oneway, s_1, true), new Tag(s_surface, s_compacted, true),
new Tag(s_landuse, s_basin, true), new Tag(s_amenity, s_police, true),
new Tag(s_railway, s_tram, true), new Tag(s_route, s_road, true),
new Tag(s_natural, s_cliff, true), new Tag(s_highway, s_construction, true),
new Tag(s_aeroway, s_aerodrome, true), new Tag(s_entrance, s_yes, true),
new Tag(s_man_made, s_storage_tank, true), new Tag(s_amenity, s_atm, true),
new Tag(s_tourism, s_attraction, true), new Tag(s_route, s_bus, true),
new Tag(s_shop, s_bakery, true), new Tag(s_tourism, s_viewpoint, true),
new Tag(s_amenity, s_swimming_pool, true), new Tag(s_natural, s_beach, true),
new Tag(s_tourism, s_picnic_site, true), new Tag(s_oneway, s_true, true),
new Tag(s_highway, s_bridleway, true), new Tag(s_tourism, s_camp_site, true),
new Tag(s_abutters, s_residential, true),
new Tag(s_leisure, s_nature_reserve, true),
new Tag(s_amenity, s_drinking_water, true), new Tag(s_shop, s_clothes, true),
new Tag(s_natural, s_heath, true),
new Tag(s_highway, s_mini_roundabout, true),
new Tag(s_landuse, s_construction, true),
new Tag(s_amenity, s_waste_basket, true),
new Tag(s_railway, s_platform, true), new Tag(s_amenity, s_townhall, true),
new Tag(s_shop, s_hairdresser, true), new Tag(s_amenity, s_shelter, true),
new Tag(s_admin_level, s_9, true),
new Tag(s_building, s_farm_auxiliary, true),
new Tag(s_amenity, s_library, true), new Tag(s_building, s_detached, true),
new Tag(s_admin_level, s_4, true), new Tag(s_landuse, s_village_green, true),
new Tag(s_barrier, s_stile, true), new Tag(s_landuse, s_garages, true),
new Tag(s_amenity, s_bar, true), new Tag(s_railway, s_buffer_stop, true),
new Tag(s_wetland, s_marsh, true), new Tag(s_tourism, s_museum, true),
new Tag(s_barrier, s_cycle_barrier, true), new Tag(s_route, s_bicycle, true),
new Tag(s_railway, s_tram_stop, true),
new Tag(s_amenity, s_parking_space, true),
new Tag(s_barrier, s_retaining_wall, true),
new Tag(s_landuse, s_recreation_ground, true),
new Tag(s_amenity, s_university, true),
new Tag(s_highway, s_tertiary_link, true),
new Tag(s_building, s_terrace, true), new Tag(s_shop, s_car_repair, true),
new Tag(s_amenity, s_hunting_stand, true),
new Tag(s_amenity, s_fountain, true), new Tag(s_man_made, s_pipeline, true),
new Tag(s_wetland, s_swamp, true), new Tag(s_shop, s_car, true),
new Tag(s_bench, s_no, true), new Tag(s_tunnel, s_culvert, true),
new Tag(s_building, s_school, true), new Tag(s_barrier, s_entrance, true),
new Tag(s_railway, s_disused, true), new Tag(s_railway, s_crossing, true),
new Tag(s_building, s_church, true),
new Tag(s_amenity, s_social_facility, true), new Tag(s_natural, s_bay, true),
new Tag(s_shop, s_kiosk, true), new Tag(s_amenity, s_vending_machine, true),
new Tag(s_route, s_hiking, true), new Tag(s_natural, s_spring, true),
new Tag(s_leisure, s_common, true), new Tag(s_railway, s_switch, true),
new Tag(s_waterway, s_rapids, true), new Tag(s_admin_level, s_7, true),
new Tag(s_leisure, s_stadium, true), new Tag(s_leisure, s_track, true),
new Tag(s_place, s_isolated_dwelling, true), new Tag(s_place, s_islet, true),
new Tag(s_waterway, s_weir, true), new Tag(s_amenity, s_doctors, true),
new Tag(s_access, s_designated, true),
new Tag(s_landuse, s_conservation, true),
new Tag(s_waterway, s_artificial, true),
new Tag(s_amenity, s_bus_station, true),
new Tag(s_leisure, s_golf_course, true),
new Tag(s_shop, s_doityourself, true), new Tag(s_building, s_service, true),
new Tag(s_tourism, s_guest_house, true), new Tag(s_aeroway, s_runway, true),
new Tag(s_place, s_city, true), new Tag(s_railway, s_subway, true),
new Tag(s_man_made, s_wastewater_plant, true),
new Tag(s_building, s_commercial, true), new Tag(s_railway, s_halt, true),
new Tag(s_amenity, s_emergency_phone, true),
new Tag(s_building, s_retail, true), new Tag(s_barrier, s_block, true),
new Tag(s_leisure, s_recreation_ground, true),
new Tag(s_access, s_forestry, true), new Tag(s_amenity, s_college, true),
new Tag(s_highway, s_platform, true), new Tag(s_access, s_unknown, true),
new Tag(s_man_made, s_water_tower, true),
new Tag(s_surface, s_pebblestone, true), new Tag(s_bridge, s_viaduct, true),
new Tag(s_shop, s_butcher, true), new Tag(s_shop, s_florist, true),
new Tag(s_boundary, s_landuse, true), new Tag(s_aeroway, s_helipad, true),
new Tag(s_building, s_hangar, true), new Tag(s_natural, s_glacier, true),
new Tag(s_highway, s_proposed, true), new Tag(s_shop, s_mall, true),
new Tag(s_barrier, s_toll_booth, true),
new Tag(s_amenity, s_fire_hydrant, true),
new Tag(s_building, s_manufacture, true), new Tag(s_building, s_farm, true),
new Tag(s_surface, s_wood, true), new Tag(s_amenity, s_car_wash, true),
new Tag(s_amenity, s_dentist, true), new Tag(s_natural, s_marsh, true),
new Tag(s_man_made, s_surveillance, true), new Tag(s_shop, s_bicycle, true),
new Tag(s_route, s_foot, true), new Tag(s_amenity, s_theatre, true),
new Tag(s_building, s_office, true), new Tag(s_railway, s_light_rail, true),
new Tag(s_man_made, s_petroleum_well, true),
new Tag(s_amenity, s_taxi, true), new Tag(s_building, s_greenhouse, true),
new Tag(s_landuse, s_brownfield, true),
new Tag(s_bicycle, s_permissive, true), new Tag(s_admin_level, s_2, true),
new Tag(s_aeroway, s_apron, true), new Tag(s_building, s_cabin, true),
new Tag(s_amenity, s_cinema, true), new Tag(s_access, s_customers, true),
new Tag(s_tourism, s_motel, true), new Tag(s_railway, s_narrow_gauge, true),
new Tag(s_amenity, s_marketplace, true), new Tag(s_shop, s_furniture, true),
new Tag(s_entrance, s_staircase, true), new Tag(s_tourism, s_artwork, true),
new Tag(s_natural, s_grassland, true), new Tag(s_shop, s_books, true),
new Tag(s_admin_level, s_5, true), new Tag(s_man_made, s_groyne, true),
new Tag(s_waterway, s_lock_gate, true),
new Tag(s_highway, s_emergency_access_point, true),
new Tag(s_natural, s_sand, true), new Tag(s_landuse, s_military, true),
new Tag(s_boundary, s_protected_area, true),
new Tag(s_amenity, s_community_centre, true),
new Tag(s_barrier, s_kissing_gate, true),
new Tag(s_highway, s_speed_camera, true),
new Tag(s_boundary, s_national_park, true),
new Tag(s_railway, s_subway_entrance, true),
new Tag(s_man_made, s_silo, true), new Tag(s_shop, s_alcohol, true),
new Tag(s_highway, s_give_way, true), new Tag(s_leisure, s_slipway, true),
new Tag(s_shop, s_electronics, true), new Tag(s_bicycle, s_dismount, true),
new Tag(s_leisure, s_marina, true), new Tag(s_entrance, s_main, true),
new Tag(s_boundary, s_postal_code, true),
new Tag(s_landuse, s_greenhouse_horticulture, true),
new Tag(s_highway, s_milestone, true),
new Tag(s_natural, s_cave_entrance, true),
new Tag(s_landuse, s_landfill, true), new Tag(s_shop, s_chemist, true),
new Tag(s_shop, s_shoes, true), new Tag(s_barrier, s_cattle_grid, true),
new Tag(s_landuse, s_railway, true), new Tag(s_tourism, s_hostel, true),
new Tag(s_tourism, s_chalet, true), new Tag(s_place, s_county, true),
new Tag(s_shop, s_department_store, true), new Tag(s_highway, s_ford, true),
new Tag(s_natural, s_scree, true), new Tag(s_landuse, s_greenfield, true),
new Tag(s_amenity, s_nursing_home, true),
new Tag(s_barrier, s_wire_fence, true),
new Tag(s_access, s_restricted, true),
new Tag(s_man_made, s_reservoir_covered, true),
new Tag(s_amenity, s_bicycle_rental, true), new Tag(s_man_made, s_MDF, true),
new Tag(s_man_made, s_water_well, true), new Tag(s_landuse, s_field, true),
new Tag(s_landuse, s_wood, true), new Tag(s_shop, s_hardware, true),
new Tag(s_tourism, s_alpine_hut, true), new Tag(s_natural, s_tree_row, true),
new Tag(s_tourism, s_caravan_site, true), new Tag(s_bridge, s_no, true),
new Tag(s_wetland, s_bog, true), new Tag(s_amenity, s_courthouse, true),
new Tag(s_route, s_ferry, true), new Tag(s_barrier, s_city_wall, true),
new Tag(s_amenity, s_veterinary, true), new Tag(s_shop, s_jewelry, true),
new Tag(s_building, s_transportation, true),
new Tag(s_amenity, s_arts_centre, true),
new Tag(s_bicycle, s_official, true), new Tag(s_shop, s_optician, true),
new Tag(s_shop, s_yes, true), new Tag(s_building, s_collapsed, true),
new Tag(s_shop, s_garden_centre, true), new Tag(s_man_made, s_chimney, true),
new Tag(s_man_made, s_mine, true), new Tag(s_bench, s_unknown, true),
new Tag(s_railway, s_preserved, true), new Tag(s_building, s_public, true),
new Tag(s_amenity, s_ferry_terminal, true),
new Tag(s_highway, s_raceway, true), new Tag(s_natural, s_rock, true),
new Tag(s_tunnel, s_no, true), new Tag(s_building, s_university, true),
new Tag(s_shop, s_beverages, true),
new Tag(s_amenity, s_waste_disposal, true),
new Tag(s_building, s_warehouse, true),
new Tag(s_leisure, s_water_park, true), new Tag(s_shop, s_gift, true),
new Tag(s_place, s_farm, true), new Tag(s_wetland, s_tidalflat, true),
new Tag(s_waterway, s_waterfall, true), new Tag(s_man_made, s_dolphin, true),
new Tag(s_service, s_drive_through, true),
new Tag(s_amenity, s_nightclub, true), new Tag(s_building, s_shed, true),
new Tag(s_shop, s_greengrocer, true), new Tag(s_natural, s_fell, true),
new Tag(s_wetland, s_wet_meadow, true), new Tag(s_aeroway, s_gate, true),
new Tag(s_shop, s_computer, true), new Tag(s_man_made, s_lighthouse, true),
new Tag(s_wetland, s_reedbed, true), new Tag(s_man_made, s_breakwater, true),
new Tag(s_surface, s_Dirt_Sand, true), new Tag(s_barrier, s_ditch, true),
new Tag(s_barrier, s_yes, true), new Tag(s_amenity, s_biergarten, true),
new Tag(s_shop, s_mobile_phone, true), new Tag(s_route, s_mtb, true),
new Tag(s_amenity, s_grit_bin, true), new Tag(s_amenity, s_bbq, true),
new Tag(s_shop, s_sports, true), new Tag(s_barrier, s_wood_fence, true),
new Tag(s_entrance, s_home, true), new Tag(s_shop, s_laundry, true),
new Tag(s_man_made, s_gasometer, true),
new Tag(s_barrier, s_embankment, true), new Tag(s_shop, s_toys, true),
new Tag(s_wetland, s_saltmarsh, true), new Tag(s_waterway, s_soakhole, true),
new Tag(s_shop, s_travel_agency, true),
new Tag(s_man_made, s_water_works, true), new Tag(s_route, s_railway, true),
new Tag(s_amenity, s_prison, true), new Tag(s_highway, s_rest_area, true),
new Tag(s_shop, s_stationery, true), new Tag(s_admin_level, s_11, true),
new Tag(s_building, s_train_station, true),
new Tag(s_building, s_storage_tank, true),
new Tag(s_man_made, s_windmill, true), new Tag(s_shop, s_beauty, true),
new Tag(s_building, s_semi, true), new Tag(s_highway, s_services, true),
new Tag(s_bicycle, s_private, true), new Tag(s_route, s_ski, true),
new Tag(s_service, s_emergency_access, true),
new Tag(s_building, s_factory, true),
new Tag(s_man_made, s_reinforced_slope, true),
new Tag(s_amenity, s_car_sharing, true), new Tag(s_surface, s_earth, true),
new Tag(s_shop, s_hifi, true), new Tag(s_amenity, s_car_rental, true),
new Tag(s_barrier, s_hedge_bank, true),
new Tag(s_shop, s_confectionery, true), new Tag(s_aeroway, s_terminal, true),
new Tag(s_highway, s_passing_place, true),
new Tag(s_building, s_building, true), new Tag(s_man_made, s_dyke, true),
new Tag(s_building, s_construction, true), new Tag(s_building, s_shop, true),
new Tag(s_natural, s_reef, true), new Tag(s_landuse, s_aquaculture, true),
new Tag(s_shop, s_dry_cleaning, true), new Tag(s_amenity, s_embassy, true),
new Tag(s_shop, s_newsagent, true), new Tag(s_landuse, s_salt_pond, true),
new Tag(s_railway, s_spur, true), new Tag(s_wheelchair, s_unknown, true),
new Tag(s_tourism, s_zoo, true), new Tag(s_man_made, s_waterway, true),
new Tag(s_surface, s_fine_gravel, true), new Tag(s_shop, s_motorcycle, true),
new Tag(s_building, s_Building, true),
new Tag(s_railway, s_construction, true),
new Tag(s_place, s_neighbourhood, true), new Tag(s_route, s_train, true),
new Tag(s_building, s_no, true), new Tag(s_natural, s_mud, true),
new Tag(s_place, s_region, true),
new Tag(s_landuse, s_reservoir_watershed, true),
new Tag(s_boundary, s_marker, true), new Tag(s_man_made, s_beacon, true),
new Tag(s_shop, s_outdoor, true), new Tag(s_access, s_public, true),
new Tag(s_abutters, s_industrial, true), new Tag(s_building, s_barn, true),
new Tag(s_leisure, s_picnic_table, true),
new Tag(s_building, s_hospital, true), new Tag(s_access, s_official, true),
new Tag(s_shop, s_variety_store, true), new Tag(s_man_made, s_crane, true),
new Tag(s_amenity, s_parking_fuel, true), new Tag(s_route, s_tram, true),
new Tag(s_tourism, s_theme_park, true), new Tag(s_shop, s_pet, true),
new Tag(s_building, s_kindergarten, true),
new Tag(s_man_made, s_storage, true), new Tag(s_man_made, s_mast, true),
new Tag(s_amenity, s_parking_entrance, true),
new Tag(s_amenity, s_clock, true),
new Tag(s_landuse, s_industrial_retail, true),
new Tag(s_shop, s_video, true), new Tag(s_access, s_delivery, true),
new Tag(s_amenity, s_driving_school, true), new Tag(s_service, s_yes, true),
new Tag(s_natural, s_bare_rock, true), new Tag(s_building, s_chapel, true),
new Tag(s_natural, s_volcano, true), new Tag(s_waterway, s_dock, true),
new Tag(s_building, s_dormitory, true),
new Tag(s_amenity, s_boat_storage, true), new Tag(s_man_made, s_tank, true),
new Tag(s_man_made, s_flagpole, true),
new Tag(s_surface, s_grass_paver, true), new Tag(s_shop, s_organic, true),
new Tag(s_natural, s_landform, true), new Tag(s_highway, s_unsurfaced, true),
new Tag(s_route, s_power, true), new Tag(s_surface, s_mud, true),
new Tag(s_building, s_building_concrete, true),
new Tag(s_abutters, s_retail, true), new Tag(s_building, s_store, true),
new Tag(s_shop, s_vacant, true), new Tag(s_leisure, s_miniature_golf, true),
new Tag(s_man_made, s_monitoring_station, true),
new Tag(s_natural, s_waterfall, true), new Tag(s_aeroway, s_hangar, true),
new Tag(s_shop, s_boutique, true), new Tag(s_route, s_detour, true),
new Tag(s_building, s_way, true), new Tag(s_railway, s_stop, true),
new Tag(s_amenity, s_ice_cream, true), new Tag(s_building, s_storage, true),
new Tag(s_shop, s_car_parts, true), new Tag(s_natural, s_ridge, true),
new Tag(s_shop, s_tyres, true), new Tag(s_railway, s_dismantled, true),
new Tag(s_amenity, s_shop, true), new Tag(s_landuse, s_plant_nursery, true),
new Tag(s_building, s_residentiel1, true),
new Tag(s_barrier, s_field_boundary, true),
new Tag(s_barrier, s_border_control, true),
new Tag(s_surface, s_Paved, true), new Tag(s_barrier, s_sally_port, true),
new Tag(s_amenity, s_bureau_de_change, true),
new Tag(s_leisure, s_fishing, true),
new Tag(s_amenity, s_charging_station, true),
new Tag(s_building, s_supermarket, true), new Tag(s_highway, s_stile, true),
new Tag(s_amenity, s_sauna, true), new Tag(s_place, s_municipality, true),
new Tag(s_building, s_hotel, true), new Tag(s_surface, s_metal, true),
new Tag(s_highway, s_incline_steep, true),
new Tag(s_shop, s_estate_agent, true), new Tag(s_natural, s_grass, true),
new Tag(s_shop, s_pharmacy, true),
new Tag(s_surface, s_concrete_plates, true),
new Tag(s_shop, s_copyshop, true),
new Tag(s_surface, s_paving_stones_30, true),
new Tag(s_surface, s_interlock, true), new Tag(s_access, s_hov, true),
new Tag(s_highway, s_elevator, true),
new Tag(s_boundary, s_local_authority, true),
new Tag(s_man_made, s_communications_tower, true),
new Tag(s_shop, s_deli, true), new Tag(s_barrier, s_turnstile, true),
new Tag(s_building, s_offices, true), new Tag(s_building, s_bunker, true),
new Tag(s_natural, s_stone, true),
new Tag(s_railway, s_railway_crossing, true),
new Tag(s_leisure, s_dog_park, true),
new Tag(s_building, s_semi_detached, true),
new Tag(s_man_made, s_watermill, true), new Tag(s_route, s_trolleybus, true),
new Tag(s_admin_level, s_3, true), new Tag(s_building, s_block, true),
new Tag(s_barrier, s_guard_rail, true), new Tag(s_bicycle, s_unknown, true),
new Tag(s_highway, s_abandoned, true), new Tag(s_surface, s_dirt_sand, true),
new Tag(s_barrier, s_chain, true), new Tag(s_barrier, s_bump_gate, true),
new Tag(s_building, s_residental, true), new Tag(s_surface, s_cement, true),
new Tag(s_man_made, s_embankment, true), new Tag(s_building, s_ruins, true),
new Tag(s_highway, s_incline, true), new Tag(s_abutters, s_commercial, true),
new Tag(s_barrier, s_hampshire_gate, true), new Tag(s_shop, s_music, true),
new Tag(s_shop, s_funeral_directors, true),
new Tag(s_wetland, s_mangrove, true), new Tag(s_place, s_borough, true),
new Tag(s_building, s_apartment, true), new Tag(s_boundary, s_census, true),
new Tag(s_barrier, s_kerb, true), new Tag(s_building, s_glasshouse, true),
new Tag(s_aeroway, s_holding_position, true),
new Tag(s_shop, s_general, true), new Tag(s_building, s_tank, true),
new Tag(s_railway, s_monorail, true), new Tag(s_service, s_parking, true),
new Tag(s_place, s_state, true), new Tag(s_railway, s_proposed, true),
new Tag(s_shop, s_art, true), new Tag(s_natural, s_hill, true),
new Tag(s_railway, s_turntable, true), new Tag(s_tourism, s_cabin, true),
new Tag(s_shop, s_photo, true), new Tag(s_boundary, s_lot, true),
new Tag(s_shop, s_fishmonger, true), new Tag(s_amenity, s_clinic, true),
new Tag(s_boundary, s_political, true), new Tag(s_man_made, s_well, true),
new Tag(s_highway, s_byway, true), new Tag(s_leisure, s_horse_riding, true),
new Tag(s_service, s_bus, true), new Tag(s_building, s_tower, true),
new Tag(s_entrance, s_service, true), new Tag(s_shop, s_fabric, true),
new Tag(s_railway, s_miniature, true), new Tag(s_abutters, s_mixed, true),
new Tag(s_surface, s_stone, true), new Tag(s_access, s_emergency, true),
new Tag(s_landuse, s_mine, true), new Tag(s_amenity, s_shower, true),
new Tag(s_waterway, s_lock, true)
};
}

View File

@ -33,13 +33,18 @@ import org.mapsforge.database.FileOpenResult;
import org.mapsforge.database.IMapDatabase;
import org.mapsforge.database.IMapDatabaseCallback;
import org.mapsforge.database.MapFileInfo;
import org.mapsforge.database.QueryResult;
import org.postgresql.PGConnection;
import android.util.Log;
/**
*
*
*/
public class MapDatabase implements IMapDatabase {
private final static String TAG = "MapDatabase";
private static final String QUERY = "SELECT tags, geom FROM __get_tile(?,?,?)";
private final float mScale = 1; // 1000000.0f;
@ -47,7 +52,7 @@ public class MapDatabase implements IMapDatabase {
private int mCoordPos = 0;
private int mIndexPos = 0;
private float[] mCoords = new float[100000];
private int[] mIndex = new int[10000];
private short[] mIndex = new short[10000];
private Tag[] mTags;
@ -66,7 +71,7 @@ public class MapDatabase implements IMapDatabase {
private boolean connect() {
Connection conn = null;
String dburl = "jdbc:postgresql://city.informatik.uni-bremen.de:5432/gis";
String dburl = "jdbc:postgresql://city.informatik.uni-bremen.de:5432/gis-2.0";
Properties dbOpts = new Properties();
dbOpts.setProperty("user", "osm");
@ -97,44 +102,45 @@ public class MapDatabase implements IMapDatabase {
}
@Override
public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
public QueryResult executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
if (connection == null) {
if (!connect())
return;
return QueryResult.FAILED;
}
ResultSet r;
try {
prepQuery.setLong(1, tile.pixelX);
prepQuery.setLong(2, tile.pixelY);
prepQuery.setLong(1, tile.tileX * 256);
prepQuery.setLong(2, tile.tileY * 256);
prepQuery.setInt(3, tile.zoomLevel);
System.out.println("" + prepQuery.toString());
Log.d(TAG, "" + prepQuery.toString());
prepQuery.execute();
r = prepQuery.getResultSet();
} catch (SQLException e) {
e.printStackTrace();
connection = null;
return;
return QueryResult.FAILED;
}
byte[] b = null;
PGHStore h = null;
int cnt = 0;
try {
while (r != null && r.next()) {
mIndexPos = 0;
mCoordPos = 0;
cnt++;
try {
Object obj = r.getObject(1);
h = null;
if (obj instanceof PGHStore)
h = (PGHStore) obj;
else
else {
Log.d(TAG, "no tags: skip way");
continue;
}
b = r.getBytes(2);
} catch (SQLException e) {
@ -142,15 +148,16 @@ public class MapDatabase implements IMapDatabase {
continue;
}
if (b == null)
if (b == null) {
// Log.d(TAG, "no geometry: skip way");
continue;
}
mTags = new Tag[h.size()];
int i = 0;
for (Entry<String, String> t : h.entrySet()) {
if (t.getKey() == null) {
System.out.println("no KEY !!! ");
Log.d(TAG, "no KEY !!! ");
break;
}
Tag tag = tagHash.get(t);
@ -164,18 +171,27 @@ public class MapDatabase implements IMapDatabase {
if (i < mTags.length)
continue;
parse(b);
if (mIndexPos == 0)
boolean polygon = parse(b);
if (mIndexPos == 0) {
Log.d(TAG, "no index: skip way");
continue;
} else if (mIndexPos == 1) {
mapDatabaseCallback.renderPointOfInterest((byte) 0, mCoords[1],
mCoords[0], mTags);
} else {
int[] idx = new int[mIndexPos];
System.arraycopy(mIndex, 0, idx, 0, mIndexPos);
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, idx, true);
short[] idx = new short[mIndexPos];
System.arraycopy(mIndex, 0, idx, 0, mIndexPos);
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, idx, polygon);
}
}
} catch (SQLException e) {
e.printStackTrace();
connection = null;
return QueryResult.FAILED;
}
// Log.d(TAG, "rows: " + cnt);
return QueryResult.SUCCESS;
}
@Override
@ -237,11 +253,11 @@ public class MapDatabase implements IMapDatabase {
* @param value
* ...
*/
private void parse(byte[] value) {
parseGeometry(valueGetterForEndian(value));
private boolean parse(byte[] value) {
return parseGeometry(valueGetterForEndian(value));
}
private void parseGeometry(ValueGetter data) {
private boolean parseGeometry(ValueGetter data) {
byte endian = data.getByte(); // skip and test endian flag
if (endian != data.endian) {
throw new IllegalArgumentException("Endian inconsistency!");
@ -255,7 +271,7 @@ public class MapDatabase implements IMapDatabase {
boolean haveS = (typeword & 0x20000000) != 0;
// int srid = Geometry.UNKNOWN_SRID;
boolean polygon = false;
if (haveS) {
// srid = Geometry.parseSRID(data.getInt());
data.getInt();
@ -269,6 +285,7 @@ public class MapDatabase implements IMapDatabase {
break;
case Geometry.POLYGON:
parsePolygon(data, haveZ, haveM);
polygon = true;
break;
case Geometry.MULTIPOINT:
parseMultiPoint(data);
@ -278,6 +295,7 @@ public class MapDatabase implements IMapDatabase {
break;
case Geometry.MULTIPOLYGON:
parseMultiPolygon(data);
polygon = true;
break;
case Geometry.GEOMETRYCOLLECTION:
parseCollection(data);
@ -288,14 +306,16 @@ public class MapDatabase implements IMapDatabase {
// if (srid != Geometry.UNKNOWN_SRID) {
// result.setSrid(srid);
// }
return polygon;
}
private static void parsePoint(ValueGetter data, boolean haveZ, boolean haveM) {
private void parsePoint(ValueGetter data, boolean haveZ, boolean haveM) {
// double X = data.getDouble();
// double Y = data.getDouble();
data.getDouble();
data.getDouble();
mCoords[0] = (float) (data.getDouble() * mScale);
mCoords[1] = (float) (data.getDouble() * mScale);
mIndex[0] = 2;
mIndexPos = 1;
if (haveZ)
data.getDouble();
@ -341,7 +361,7 @@ public class MapDatabase implements IMapDatabase {
if (haveM)
data.getDouble();
}
mIndex[mIndexPos++] = count * 2;
mIndex[mIndexPos++] = (short) (count * 2);
}
private void parsePolygon(ValueGetter data, boolean haveZ, boolean haveM) {