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_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">Tile coordinates</string>
<string name="preferences_show_tile_coordinates_desc">Show coordinates on tiles</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_show_tile_frames_desc">Draw tile boundaries</string>
<string name="preferences_disable_polygons">Disable Polygon rendering</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> <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" /> --> android:key="showFpsCounter" /> -->
<CheckBoxPreference android:title="@string/preferences_show_tile_frames" android:summary="@string/preferences_show_tile_frames_desc" <CheckBoxPreference android:title="@string/preferences_show_tile_frames" android:summary="@string/preferences_show_tile_frames_desc"
android:key="drawTileFrames" /> android:key="drawTileFrames" />
<!-- <CheckBoxPreference android:title="@string/preferences_show_tile_coordinates" android:summary="@string/preferences_show_tile_coordinates_desc" <CheckBoxPreference android:title="@string/preferences_show_unmatched_ways" android:summary="@string/preferences_show_unmatched_ways"
android:key="drawTileCoordinates" /> --> android:key="drawUnmatchedWays" />
<CheckBoxPreference android:title="@string/preferences_disable_polygons" android:summary="@string/preferences_disable_polygons" <CheckBoxPreference android:title="@string/preferences_disable_polygons" android:summary="@string/preferences_disable_polygons"
android:key="disablePolygons" /> android:key="disablePolygons" />
</PreferenceCategory> </PreferenceCategory>

View File

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

View File

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

View File

@ -14,35 +14,27 @@
*/ */
package org.mapsforge.android.glrenderer; package org.mapsforge.android.glrenderer;
import java.util.LinkedList;
class Layer { class Layer {
LinkedList<PoolItem> pool; PoolItem pool;
protected PoolItem curItem; protected PoolItem curItem;
int verticesCnt; int verticesCnt;
int offset; int offset;
final int layer; final int layer;
// final int color;
final float[] colors;
Layer(int l, int color) { Layer(int l) {
layer = l; layer = l;
verticesCnt = 0; 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() { float[] getNextPoolItem() {
curItem.used = PoolItem.SIZE; curItem.used = PoolItem.SIZE;
curItem = LayerPool.get();
pool.add(curItem); curItem.next = VertexPool.get();
curItem = curItem.next;
return curItem.vertices; return curItem.vertices;
} }
} }

View File

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

View File

@ -19,42 +19,17 @@ import java.nio.ByteOrder;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import android.util.SparseArray;
class LineLayers { class LineLayers {
private static int NUM_VERTEX_FLOATS = 4; private static int NUM_VERTEX_FLOATS = 4;
private SparseArray<LineLayer> layers; static FloatBuffer compileLayerData(LineLayer layers, FloatBuffer buf) {
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) {
FloatBuffer fbuf = 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++) { size *= NUM_VERTEX_FLOATS;
LineLayer l = layers.valueAt(i);
array[i] = l;
size += l.verticesCnt * NUM_VERTEX_FLOATS;
}
if (buf == null || buf.capacity() < size) { if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order( ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order(
@ -65,40 +40,42 @@ class LineLayers {
} }
int pos = 0; int pos = 0;
for (int i = 0, n = array.length; i < n; i++) { PoolItem last = null, items = null;
LineLayer l = array[i];
for (LineLayer l = layers; l != null; l = l.next) {
if (l.isOutline) if (l.isOutline)
continue; continue;
for (PoolItem item : l.pool) { for (PoolItem item = l.pool; item != null; item = item.next) {
fbuf.put(item.vertices, 0, item.used); fbuf.put(item.vertices, 0, item.used);
last = item;
} }
l.offset = pos; l.offset = pos;
pos += l.verticesCnt; pos += l.verticesCnt;
LayerPool.add(l.pool); if (last != null) {
last.next = items;
items = l.pool;
}
l.pool = null; l.pool = null;
} }
fbuf.flip(); VertexPool.add(items);
// not needed for drawing fbuf.flip();
layers = null;
return fbuf; return fbuf;
} }
ShortBuffer compileLayerData(ShortBuffer buf) { static ShortBuffer compileLayerData(LineLayer layers, ShortBuffer buf) {
int size = 0;
ShortBuffer sbuf = buf; 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++) { size *= NUM_VERTEX_FLOATS;
LineLayer l = layers.valueAt(i);
array[i] = l;
size += l.verticesCnt * NUM_VERTEX_FLOATS;
}
if (buf == null || buf.capacity() < size) { if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 2).order( ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 2).order(
@ -111,29 +88,40 @@ class LineLayers {
short[] data = new short[PoolItem.SIZE]; short[] data = new short[PoolItem.SIZE];
for (int i = 0, n = array.length; i < n; i++) { PoolItem last = null, items = null;
LineLayer l = array[i];
for (LineLayer l = layers; l != null; l = l.next) {
if (l.isOutline) if (l.isOutline)
continue; continue;
for (int k = 0, m = l.pool.size(); k < m; k++) { for (PoolItem item = l.pool; item != null; item = item.next) {
PoolItem item = l.pool.get(k);
PoolItem.toHalfFloat(item, data); PoolItem.toHalfFloat(item, data);
sbuf.put(data, 0, item.used); sbuf.put(data, 0, item.used);
last = item;
} }
l.offset = pos; l.offset = pos;
pos += l.verticesCnt; pos += l.verticesCnt;
LayerPool.add(l.pool); if (last != null) {
last.next = items;
items = l.pool;
}
l.pool = null; l.pool = null;
} }
sbuf.flip(); VertexPool.add(items);
// not needed for drawing sbuf.flip();
layers = null;
return sbuf; 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; package org.mapsforge.android.glrenderer;
import java.util.ArrayList;
import org.mapsforge.android.mapgenerator.IMapGenerator; import org.mapsforge.android.mapgenerator.IMapGenerator;
import org.mapsforge.android.mapgenerator.MapGeneratorJob; import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.rendertheme.IRenderCallback; import org.mapsforge.android.rendertheme.IRenderCallback;
import org.mapsforge.android.rendertheme.RenderTheme; import org.mapsforge.android.rendertheme.RenderTheme;
import org.mapsforge.android.rendertheme.renderinstruction.Area; 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.Line;
import org.mapsforge.android.rendertheme.renderinstruction.RenderInstruction; import org.mapsforge.android.rendertheme.renderinstruction.RenderInstruction;
import org.mapsforge.core.MercatorProjection; import org.mapsforge.core.MercatorProjection;
@ -27,9 +30,9 @@ import org.mapsforge.core.Tile;
import org.mapsforge.core.WebMercator; import org.mapsforge.core.WebMercator;
import org.mapsforge.database.IMapDatabase; import org.mapsforge.database.IMapDatabase;
import org.mapsforge.database.IMapDatabaseCallback; import org.mapsforge.database.IMapDatabaseCallback;
import org.mapsforge.database.QueryResult;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.util.Log; import android.util.Log;
@ -54,11 +57,14 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
private GLMapTile mCurrentTile; private GLMapTile mCurrentTile;
private float[] mWayNodes; private float[] mWayNodes;
private int[] mWays; private short[] mWays;
private LineLayers mLineLayers; private LineLayer mLineLayers;
private PolygonLayers mPolyLayers; private PolygonLayer mPolyLayers;
// private MeshLayers mMeshLayers; private LineLayer mCurLineLayer;
private PolygonLayer mCurPolyLayer;
private ArrayList<TextItem> mLabels;
private int mDrawingLayer; private int mDrawingLayer;
private int mLevels; private int mLevels;
@ -71,13 +77,60 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
*/ */
public MapGenerator() { public MapGenerator() {
Log.d(TAG, "init DatabaseRenderer"); 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 @Override
public void renderPointOfInterest(byte layer, int latitude, int longitude, Tag[] tags) { public void renderPointOfInterest(byte layer, float latitude, float longitude,
// TODO Auto-generated method stub 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 @Override
@ -94,7 +147,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
if (mProjected) if (mProjected)
return mProjectedResult; 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; 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); lat = (float) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
} }
if (area && i == 0) { // if (area && i == 0) {
if (lon < minx) // if (lon < minx)
minx = lon; // minx = lon;
if (lon > maxx) // if (lon > maxx)
maxx = lon; // maxx = lon;
if (lat < miny) // if (lat < miny)
miny = lat; // miny = lat;
if (lat > maxy) // if (lat > maxy)
maxy = lat; // maxy = lat;
} // }
if (cnt != 0) { if (cnt != 0) {
// drop small distance intermediate nodes // drop small distance intermediate nodes
@ -161,38 +214,44 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
cnt += 2; cnt += 2;
} }
if (area) { // if (area) {
// Log.d(TAG, "area:" + (maxx - minx) * (maxy - miny)); // // Log.d(TAG, "area:" + (maxx - minx) * (maxy - miny));
if ((maxx - minx) * (maxy - miny) < 2000 / mCurrentTile.zoomLevel) { // if ((maxx - minx) * (maxy - miny) < 2000 / mCurrentTile.zoomLevel) {
mProjected = true; // mProjected = true;
mProjectedResult = false; // mProjectedResult = false;
return false; // return false;
} // }
} // }
mWays[i] = cnt; mWays[i] = (short) cnt;
} }
mProjected = true; mProjected = true;
mProjectedResult = true; mProjectedResult = true;
return true; return true;
} }
private boolean firstMatch; // private boolean firstMatch;
private boolean prevClosed; // private boolean prevClosed;
private RenderInstruction[] mRenderInstructions = null; private RenderInstruction[] mRenderInstructions = null;
private final String TAG_WATER = "water".intern();
@Override @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) { boolean changed) {
// Log.d(TAG, "render way: " + layer);
mTagName = null;
mProjected = false; mProjected = false;
mDrawingLayer = getValidLayer(layer) * mLevels; mDrawingLayer = getValidLayer(layer) * mLevels;
int len = wayLength[0]; // int len = wayLength[0];
boolean closed = (wayNodes[0] == wayNodes[len - 2] && // boolean closed = (wayNodes[0] == wayNodes[len - 2] &&
wayNodes[1] == wayNodes[len - 1]); // wayNodes[1] == wayNodes[len - 1]);
boolean closed = changed;
mSimplify = 0.5f; mSimplify = 0.5f;
if (closed) { if (closed) {
@ -201,36 +260,76 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
else else
mSimplify = 0.2f; mSimplify = 0.2f;
if (tags.length == 1 && "water".equals(tags[0].value)) if (tags.length == 1 && TAG_WATER == (tags[0].value))
mSimplify = 0; mSimplify = 0;
} }
mWayNodes = wayNodes; mWayNodes = wayNodes;
mWays = wayLength; mWays = wayLength;
if (!firstMatch && prevClosed == closed && !changed) { // if (mRenderInstructions != null) {
if (mRenderInstructions != null) { // for (int i = 0, n = mRenderInstructions.length; i < n; i++)
for (int i = 0, n = mRenderInstructions.length; i < n; i++) // mRenderInstructions[i].renderWay(this, tags);
mRenderInstructions[i].renderWay(this, tags); // }
}
// MapGenerator.renderTheme.matchWay(this, tags, // prevClosed = closed;
// (byte) (mCurrentTile.zoomLevel + 0), mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags,
// closed, false); (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 { } else {
prevClosed = closed; mRenderInstructions = MapGenerator.renderTheme.matchWay(this, debugTagWay,
mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags, (byte) 0, true, true);
(byte) (mCurrentTile.zoomLevel + 0),
closed, true);
} }
firstMatch = false;
} }
@Override @Override
public void renderAreaCaption(String caption, float verticalOffset, Paint paint, public void renderAreaCaption(Caption caption) {
Paint stroke) { // Log.d(TAG, "renderAreaCaption: " + mTagName);
// TODO Auto-generated method stub
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 @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 @Override
public void renderPointOfInterestCircle(float radius, Paint fill, int level) { public void renderPointOfInterestCircle(float radius, Paint fill, int level) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
@ -260,12 +352,60 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
@Override @Override
public void renderWay(Line line) { public void renderWay(Line line) {
projectToTile(false); projectToTile(false);
LineLayer outlineLayer = null; LineLayer outlineLayer = null;
LineLayer l = mLineLayers.getLayer(mDrawingLayer + line.level, line.color, false, LineLayer lineLayer = null;
line.fixed);
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; float w = line.strokeWidth;
@ -273,13 +413,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
w *= mStrokeScale; w *= mStrokeScale;
w *= mProjectionScaleFactor; w *= mProjectionScaleFactor;
} }
if (line.outline != -1) { else {
Line outline = MapGenerator.renderTheme.getOutline(line.outline); w *= 1.2; // TODO make this dependent on dpi
if (outline != null) {
outlineLayer = mLineLayers.getLayer(mDrawingLayer + outline.level,
outline.color, true, false);
outlineLayer.addOutline(l);
}
} }
for (int i = 0, pos = 0, n = mWays.length; i < n; i++) { 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 // need at least two points
if (length >= 4) if (length >= 4)
l.addLine(mWayNodes, pos, length, w, line.round); lineLayer.addLine(mWayNodes, pos, length, w, line.round);
pos += length; 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 @Override
@ -302,17 +471,41 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
if (!projectToTile(false)) if (!projectToTile(false))
return; return;
PolygonLayer l = mPolyLayers.getLayer(mDrawingLayer + area.level, area.color, int numLayer = mDrawingLayer + area.level;
area.fade); PolygonLayer layer = null;
// MeshLayer l = mMeshLayers.getLayer(mDrawingLayer + area.level, area.color, if (mCurPolyLayer != null && mCurPolyLayer.layer == numLayer) {
// area.fade); 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++) { for (int i = 0, pos = 0, n = mWays.length; i < n; i++) {
int length = mWays[i]; int length = mWays[i];
// need at least three points // need at least three points
if (length >= 6) if (length >= 6)
l.addPolygon(mWayNodes, pos, length); layer.addPolygon(mWayNodes, pos, length);
pos += length; pos += length;
} }
@ -338,10 +531,10 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
} }
private boolean mDebugDrawPolygons; private boolean mDebugDrawPolygons;
boolean mDebugDrawUnmatched;
@Override @Override
public boolean executeJob(MapGeneratorJob mapGeneratorJob) { public boolean executeJob(MapGeneratorJob mapGeneratorJob) {
// Log.d(TAG, "load " + mCurrentTile);
if (!(mapGeneratorJob.tile instanceof GLMapTile)) if (!(mapGeneratorJob.tile instanceof GLMapTile))
return false; return false;
@ -353,7 +546,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mCurrentTile = (GLMapTile) mapGeneratorJob.tile; mCurrentTile = (GLMapTile) mapGeneratorJob.tile;
mDebugDrawPolygons = !mapGeneratorJob.debugSettings.mDisablePolygons; mDebugDrawPolygons = !mapGeneratorJob.debugSettings.mDisablePolygons;
mDebugDrawUnmatched = mapGeneratorJob.debugSettings.mDrawUnmatchted;
if (mCurrentTile.isLoading || mCurrentTile.isDrawn) if (mCurrentTile.isLoading || mCurrentTile.isDrawn)
return false; return false;
@ -363,32 +556,49 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
setScaleStrokeWidth(mCurrentTile.zoomLevel); setScaleStrokeWidth(mCurrentTile.zoomLevel);
mLineLayers = new LineLayers(); mLineLayers = null;
mPolyLayers = new PolygonLayers(); mPolyLayers = null;
// mMeshLayers = new MeshLayers(); mLabels = null;
mCurrentTile.lineLayers = mLineLayers;
mCurrentTile.polygonLayers = mPolyLayers;
// mCurrentTile.meshLayers = mMeshLayers;
firstMatch = true; // firstMatch = true;
mProjectionScaleFactor = (float) (1.0 / Math.cos(MercatorProjection mProjectionScaleFactor = (float) (1.0 / Math.cos(MercatorProjection
.pixelYToLatitude(mCurrentTile.pixelY, mCurrentTile.zoomLevel) .pixelYToLatitude(mCurrentTile.pixelY, mCurrentTile.zoomLevel)
* (Math.PI / 180))) / 1.5f; * (Math.PI / 180))); // / 1.5f;
mMapDatabase.executeQuery(mCurrentTile, this);
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) { if (mapGeneratorJob.debugSettings.mDrawTileFrames) {
float[] coords = { 0, 0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE, mTagName = new Tag("name", mCurrentTile.toString(), false);
Tile.TILE_SIZE, 0, 0, 0 }; mPoiX = 10;
LineLayer ll = mLineLayers.getLayer(Integer.MAX_VALUE, Color.BLACK, false, mPoiY = 10;
true); MapGenerator.renderTheme.matchNode(this, debugTagWay, (byte) 0);
ll.addLine(coords, 0, coords.length, 1.5f, false); // 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; mCurrentTile.newData = true;
return true; return true;
} }
private Tag[] debugTagWay = { new Tag("debug", "way") };
private Tag[] debugTagArea = { new Tag("debug", "area") };
private float mProjectionScaleFactor; private float mProjectionScaleFactor;
private static byte getValidLayer(byte layer) { private static byte getValidLayer(byte layer) {
@ -431,4 +641,13 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
public void setRenderTheme(RenderTheme theme) { public void setRenderTheme(RenderTheme theme) {
MapGenerator.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_FLOAT;
import static android.opengl.GLES20.GL_INVERT; import static android.opengl.GLES20.GL_INVERT;
import static android.opengl.GLES20.GL_NEVER; 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_ONE_MINUS_SRC_ALPHA;
import static android.opengl.GLES20.GL_SCISSOR_TEST; import static android.opengl.GLES20.GL_SCISSOR_TEST;
import static android.opengl.GLES20.GL_SRC_ALPHA; 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.MapGeneratorJob;
import org.mapsforge.android.mapgenerator.TileCacheKey; import org.mapsforge.android.mapgenerator.TileCacheKey;
import org.mapsforge.android.mapgenerator.TileDistanceSort; import org.mapsforge.android.mapgenerator.TileDistanceSort;
import org.mapsforge.android.rendertheme.renderinstruction.Line;
import org.mapsforge.android.utils.GlConfigChooser; import org.mapsforge.android.utils.GlConfigChooser;
import org.mapsforge.android.utils.GlUtils; import org.mapsforge.android.utils.GlUtils;
import org.mapsforge.core.MapPosition; import org.mapsforge.core.MapPosition;
@ -102,7 +104,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// private boolean mTriangulate = false; // 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 CACHE_TILES = CACHE_TILES_MAX;
private static int LIMIT_BUFFERS = 20 * MB; private static int LIMIT_BUFFERS = 20 * MB;
@ -127,28 +129,29 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private JobParameters mJobParameter; private JobParameters mJobParameter;
private MapPosition mMapPosition, mPrevMapPosition; private MapPosition mMapPosition, mPrevMapPosition;
private int mWidth, mHeight; private static int mWidth, mHeight;
private float mAspect; private static float mAspect;
// draw position is updated from current position in onDrawFrame // draw position is updated from current position in onDrawFrame
// keeping the position consistent while drawing // keeping the position consistent while drawing
private double mDrawX, mDrawY, mDrawZ, mCurX, mCurY, mCurZ; private static double mDrawX, mDrawY, mDrawZ, mCurX, mCurY, mCurZ;
private float mDrawScale, mCurScale; private static float mDrawScale, mCurScale;
// current center tile // current center tile
private long mTileX, mTileY; private static long mTileX, mTileY;
private FloatBuffer floatBuffer[]; private static int rotateBuffers = 2;
private ShortBuffer shortBuffer[]; private static FloatBuffer floatBuffer[];
private static ShortBuffer shortBuffer[];
boolean useHalfFloat = false; static boolean useHalfFloat = false;
// bytes currently loaded in VBOs // bytes currently loaded in VBOs
private int mBufferMemoryUsage; private static int mBufferMemoryUsage;
// flag set by updateVisibleList when current visible tiles changed. // flag set by updateVisibleList when current visible tiles changed.
// used in onDrawFrame to nextTiles to curTiles // used in onDrawFrame to nextTiles to curTiles
private boolean mUpdateTiles; private static boolean mUpdateTiles;
class TilesData { class TilesData {
int cnt = 0; 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[] mMMatrix = new float[16];
// private float[] mRMatrix = new float[16]; // private float[] mRMatrix = new float[16];
// newTiles is set in updateVisibleList and synchronized swapped // newTiles is set in updateVisibleList and synchronized swapped
// with nextTiles on main thread. // with nextTiles on main thread.
// nextTiles is swapped with curTiles in onDrawFrame in GL 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; private boolean mInitial;
// shader handles // shader handles
private int gLineProgram; private static int lineProgram;
private int gLineVertexPositionHandle; private static int hLineVertexPosition;
private int gLineTexturePositionHandle; private static int hLineTexturePosition;
private int gLineColorHandle; private static int hLineColor;
private int gLineMatrixHandle; private static int hLineMatrix;
private int gLineModeHandle; private static int hLineMode;
private int gLineWidthHandle; private static int hLineWidth;
private int gPolygonProgram; private static int polygonProgram;
private int gPolygonVertexPositionHandle; private static int hPolygonVertexPosition;
private int gPolygonMatrixHandle; private static int hPolygonMatrix;
private int gPolygonColorHandle; private static int hPolygonColor;
/** /**
* *
@ -261,7 +264,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
GLMapTile t = mTileList.remove(j); GLMapTile t = mTileList.remove(j);
if (t.isActive) { if (t.isActive) {
// Log.d(TAG, "EEEK removing active tile"); Log.d(TAG, "EEEK removing active tile");
mTileList.add(t); mTileList.add(t);
continue; continue;
} }
@ -441,18 +444,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
updateTileDistances(); 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) { for (int i = 1; i < tiles / 2; i += 2) {
GLMapTile tmp = newTiles.tiles[i]; GLMapTile tmp = newTiles.tiles[i];
newTiles.tiles[i] = newTiles.tiles[tiles - i]; newTiles.tiles[i] = newTiles.tiles[tiles - i];
newTiles.tiles[tiles - i] = tmp; newTiles.tiles[tiles - i] = tmp;
} }
int removes = mTiles.size() - CACHE_TILES;
if (removes > 0)
Collections.sort(mTileList, mTileDistanceSort);
// pass new tile list to glThread // pass new tile list to glThread
synchronized (this) { synchronized (this) {
for (int i = 0; i < nextTiles.cnt; i++) for (int i = 0; i < nextTiles.cnt; i++)
@ -472,7 +471,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mUpdateTiles = true; mUpdateTiles = true;
} }
limitCache(removes); int removes = mTiles.size() - CACHE_TILES;
if (removes > 0) {
Collections.sort(mTileList, mTileDistanceSort);
limitCache(removes);
}
if (mJobList.size() > 0) if (mJobList.size() > 0)
mMapView.addJobs(mJobList); mMapView.addJobs(mJobList);
@ -593,7 +597,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
float alpha = 1.0f; float alpha = 1.0f;
if (l.fadeLevel >= mDrawZ) { if (l.area.fade >= mDrawZ) {
alpha = (mDrawScale > 1.3f ? mDrawScale : 1.3f) - alpha; alpha = (mDrawScale > 1.3f ? mDrawScale : 1.3f) - alpha;
if (alpha > 1.0f) if (alpha > 1.0f)
@ -608,8 +612,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
blend = false; blend = false;
} }
glUniform4f(gPolygonColorHandle, glUniform4f(hPolygonColor,
l.colors[0], l.colors[1], l.colors[2], alpha); l.area.color[0], l.area.color[1], l.area.color[2], alpha);
// set stencil buffer mask used to draw this layer // set stencil buffer mask used to draw this layer
glStencilFunc(GL_EQUAL, 0xff, 1 << c); 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) { private boolean drawPolygons(GLMapTile tile, int diff) {
int cnt = 0; int cnt = 0;
if (tile.polygonLayers == null || tile.polygonLayers.array == null) if (tile.polygonLayers == null)
return true; return true;
glScissor(tile.sx, tile.sy, tile.sw, tile.sh); 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); glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
if (useHalfFloat) { if (useHalfFloat) {
glVertexAttribPointer(gPolygonVertexPositionHandle, 2, glVertexAttribPointer(hPolygonVertexPosition, 2,
OES_HALF_FLOAT, false, 0, OES_HALF_FLOAT, false, 0,
POLYGON_VERTICES_DATA_POS_OFFSET); POLYGON_VERTICES_DATA_POS_OFFSET);
} else { } else {
glVertexAttribPointer(gPolygonVertexPositionHandle, 2, glVertexAttribPointer(hPolygonVertexPosition, 2,
GL_FLOAT, false, 0, GL_FLOAT, false, 0,
POLYGON_VERTICES_DATA_POS_OFFSET); POLYGON_VERTICES_DATA_POS_OFFSET);
} }
// glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
setMatrix(tile, diff); setMatrix(tile, diff);
glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0); glUniformMatrix4fv(hPolygonMatrix, 1, false, mMVPMatrix, 0);
boolean firstPass = true; boolean firstPass = true;
for (int i = 0, n = tile.polygonLayers.array.length; i < n; i++) { for (PolygonLayer l = tile.polygonLayers; l != null; l = l.next) {
PolygonLayer l = tile.polygonLayers.array[i];
// fade out polygon layers (set in RederTheme) // fade out polygon layers (set in RederTheme)
if (l.fadeLevel > 0 && l.fadeLevel > mDrawZ) if (l.area.fade > 0 && l.area.fade > mDrawZ)
continue; continue;
if (cnt == 0) { if (cnt == 0) {
@ -668,8 +668,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (firstPass) if (firstPass)
firstPass = false; firstPass = false;
else { else {
// eeek, nexus! - cant do old-school polygons GLES20.glFlush();
// glFinish();
// clear stencilbuffer // clear stencilbuffer
glStencilMask(0xFF); glStencilMask(0xFF);
@ -703,56 +702,16 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// eeek, nexus! - cant do old-school polygons // eeek, nexus! - cant do old-school polygons
// glFinish(); // glFinish();
} }
GLES20.glFlush();
return true; return true;
} }
private int mLastBoundVBO; private static 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 boolean drawLines(GLMapTile tile, int diff) { private boolean drawLines(GLMapTile tile, int diff) {
float z = 1; float z = 1;
if (tile.lineLayers == null || tile.lineLayers.array == null) if (tile.lineLayers == null)
return false; return false;
glScissor(tile.sx, tile.sy, tile.sw, tile.sh); 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); glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id);
if (useHalfFloat) { if (useHalfFloat) {
glVertexAttribPointer(gLineVertexPositionHandle, 2, OES_HALF_FLOAT, glVertexAttribPointer(hLineVertexPosition, 2, OES_HALF_FLOAT,
false, 8, LINE_VERTICES_DATA_POS_OFFSET); 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); false, 8, LINE_VERTICES_DATA_TEX_OFFSET >> 1);
} else { } else {
glVertexAttribPointer(gLineVertexPositionHandle, 2, GL_FLOAT, glVertexAttribPointer(hLineVertexPosition, 2, GL_FLOAT,
false, 16, LINE_VERTICES_DATA_POS_OFFSET); false, 16, LINE_VERTICES_DATA_POS_OFFSET);
glVertexAttribPointer(gLineTexturePositionHandle, 2, GL_FLOAT, glVertexAttribPointer(hLineTexturePosition, 2, GL_FLOAT,
false, 16, LINE_VERTICES_DATA_TEX_OFFSET); false, 16, LINE_VERTICES_DATA_TEX_OFFSET);
} }
// glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
if (diff != 0) if (diff != 0)
z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff); z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff);
setMatrix(tile, diff); setMatrix(tile, diff);
glUniformMatrix4fv(gLineMatrixHandle, 1, false, mMVPMatrix, 0); glUniformMatrix4fv(hLineMatrix, 1, false, mMVPMatrix, 0);
LineLayer[] layers = tile.lineLayers.array;
boolean drawOutlines = false; boolean drawOutlines = false;
boolean drawFixed = false; boolean drawFixed = false;
@ -792,52 +748,67 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// linear scale for fixed lines // linear scale for fixed lines
float fdiv = 0.9f / (mDrawScale / z); float fdiv = 0.9f / (mDrawScale / z);
// int cnt = 0; boolean first = true;
for (int i = 0, n = layers.length; i < n; i++) {
LineLayer l = layers[i]; 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 // 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; drawOutlines = l.isOutline;
drawFixed = l.isFixed; drawFixed = line.fixed;
if (drawOutlines) { if (drawOutlines) {
glUniform2f(gLineModeHandle, 0, wdiv); glUniform2f(hLineMode, 0, wdiv);
} else if (!drawFixed) { } else if (!drawFixed) {
glUniform2f(gLineModeHandle, 0, wdiv * 0.98f); glUniform2f(hLineMode, 0, wdiv * 0.98f);
} }
} }
if (drawFixed) { if (drawFixed) {
if (l.width < 1.0) if (l.width < 1.0)
glUniform2f(gLineModeHandle, 0.4f, fdiv); glUniform2f(hLineMode, 0.4f, fdiv);
else 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) { if (drawOutlines) {
for (int j = 0, m = l.outlines.size(); j < m; j++) { for (LineLayer o = l.outlines; o != null; o = o.outlines) {
LineLayer o = l.outlines.get(j);
if (mSimpleLines) if (mSimpleLines)
glUniform1f(gLineWidthHandle, o.width); glUniform1f(hLineWidth, o.width);
glDrawArrays(GL_TRIANGLE_STRIP, o.offset, o.verticesCnt); glDrawArrays(GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
} }
} }
else { else {
if (mSimpleLines) if (mSimpleLines)
glUniform1f(gLineWidthHandle, l.width); glUniform1f(hLineWidth, l.width);
glDrawArrays(GL_TRIANGLE_STRIP, l.offset, l.verticesCnt); glDrawArrays(GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
} }
} }
GLES20.glFlush();
return true; return true;
} }
private void setMatrix(GLMapTile tile, int diff) { private static void setMatrix(GLMapTile tile, int diff) {
float x, y, scale; float x, y, scale;
float z = 1; float z = 1;
@ -858,7 +829,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mMVPMatrix[5] = (scale); mMVPMatrix[5] = (scale);
} }
private boolean setTileScissor(GLMapTile tile, float div) { private static boolean setTileScissor(GLMapTile tile, float div) {
double dx, dy, scale; double dx, dy, scale;
@ -916,12 +887,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private int uploadCnt = 0; private int uploadCnt = 0;
private boolean uploadTileData(GLMapTile tile) { private boolean uploadTileData(GLMapTile tile) {
ShortBuffer sbuf = null;
FloatBuffer fbuf = null;
// double start = SystemClock.uptimeMillis(); // double start = SystemClock.uptimeMillis();
// use multiple buffers to avoid overwriting buffer while current data is uploaded // use multiple buffers to avoid overwriting buffer while current
// (or rather the blocking which is required to avoid this) // data is uploaded (or rather the blocking which is required to avoid this)
if (uploadCnt >= 10) { if (uploadCnt >= rotateBuffers) {
// mMapView.requestRender(); // mMapView.requestRender();
// return false; // return false;
uploadCnt = 0; uploadCnt = 0;
@ -939,27 +912,34 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
tile.polygonVBO = mVBOs.remove(mVBOs.size() - 1); tile.polygonVBO = mVBOs.remove(mVBOs.size() - 1);
} }
} }
if (useHalfFloat) int size = 0;
shortBuffer[uploadCnt * 2] = tile.lineLayers
.compileLayerData(shortBuffer[uploadCnt * 2]);
else
floatBuffer[uploadCnt * 2] = tile.lineLayers
.compileLayerData(floatBuffer[uploadCnt * 2]);
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; mBufferMemoryUsage -= tile.lineVBO.size;
glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id); glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id);
// glBufferData(GL_ARRAY_BUFFER, 0, null, GL_DYNAMIC_DRAW); // glBufferData(GL_ARRAY_BUFFER, 0, null, GL_DYNAMIC_DRAW);
if (useHalfFloat) { if (useHalfFloat) {
tile.lineVBO.size = tile.lineLayers.size * SHORT_BYTES; tile.lineVBO.size = size * SHORT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size, glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size,
shortBuffer[uploadCnt * 2], GL_DYNAMIC_DRAW); sbuf, GL_DYNAMIC_DRAW);
} else { } else {
tile.lineVBO.size = tile.lineLayers.size * FLOAT_BYTES; tile.lineVBO.size = size * FLOAT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size, glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size,
floatBuffer[uploadCnt * 2], GL_DYNAMIC_DRAW); fbuf, GL_DYNAMIC_DRAW);
} }
mBufferMemoryUsage += tile.lineVBO.size; mBufferMemoryUsage += tile.lineVBO.size;
@ -968,16 +948,19 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
tile.lineLayers = null; tile.lineLayers = null;
} }
// if (!mTriangulate) { if (useHalfFloat) {
if (useHalfFloat) sbuf = PolygonLayers.compileLayerData(tile.polygonLayers,
shortBuffer[uploadCnt * 2 + 1] = tile.polygonLayers shortBuffer[uploadCnt * 2 + 1]);
.compileLayerData(shortBuffer[uploadCnt * 2 + 1]); size = sbuf.remaining();
else shortBuffer[uploadCnt * 2 + 1] = sbuf;
floatBuffer[uploadCnt * 2 + 1] = tile.polygonLayers } else {
.compileLayerData(floatBuffer[uploadCnt * 2 + 1]); fbuf = PolygonLayers.compileLayerData(tile.polygonLayers,
floatBuffer[uploadCnt * 2 + 1]);
size = fbuf.remaining();
floatBuffer[uploadCnt * 2 + 1] = fbuf;
}
// Upload polygon data to vertex buffer object // Upload polygon data to vertex buffer object
if (tile.polygonLayers.size > 0) { if (size > 0) {
mBufferMemoryUsage -= tile.polygonVBO.size; mBufferMemoryUsage -= tile.polygonVBO.size;
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id); glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
@ -985,54 +968,24 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// GL_DYNAMIC_DRAW); // GL_DYNAMIC_DRAW);
if (useHalfFloat) { if (useHalfFloat) {
tile.polygonVBO.size = tile.polygonLayers.size * SHORT_BYTES; tile.polygonVBO.size = size * SHORT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size, glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
shortBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW); sbuf, GL_DYNAMIC_DRAW);
} else { } else {
tile.polygonVBO.size = tile.polygonLayers.size * FLOAT_BYTES; tile.polygonVBO.size = size * FLOAT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size, glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
floatBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW); fbuf, GL_DYNAMIC_DRAW);
} }
mBufferMemoryUsage += tile.polygonVBO.size; mBufferMemoryUsage += tile.polygonVBO.size;
} else { } else {
tile.polygonLayers = null; 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.newData = false;
tile.isDrawn = true; tile.isDrawn = true;
tile.isLoading = false; tile.isLoading = false;
// double compile = SystemClock.uptimeMillis(); // double compile = SystemClock.uptimeMillis();
// glFinish(); // glFinish();
// double now = SystemClock.uptimeMillis(); // double now = SystemClock.uptimeMillis();
@ -1044,8 +997,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
return true; return true;
} }
// private long startTime = SystemClock.uptimeMillis();
@Override @Override
public void onDrawFrame(GL10 glUnused) { public void onDrawFrame(GL10 glUnused) {
long start = 0, poly_time = 0, clear_time = 0; long start = 0, poly_time = 0, clear_time = 0;
@ -1057,20 +1008,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
start = SystemClock.uptimeMillis(); start = SystemClock.uptimeMillis();
glStencilMask(0xFF); glStencilMask(0xFF);
glDisable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 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) { synchronized (this) {
mDrawX = mCurX; mDrawX = mCurX;
mDrawY = mCurY; mDrawY = mCurY;
@ -1114,13 +1053,20 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
uploadCnt = 0; uploadCnt = 0;
mLastBoundVBO = -1; mLastBoundVBO = -1;
int updateTextures = 0;
// check visible tiles, set tile clip scissors, upload new vertex data // check visible tiles, set tile clip scissors, upload new vertex data
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
GLMapTile tile = tiles[i]; GLMapTile tile = tiles[i];
if (!setTileScissor(tile, 1)) if (!setTileScissor(tile, 1))
continue; continue;
if (tile.texture == null && tile.labels != null &&
mTextRenderer.drawToTexture(tile))
updateTextures++;
if (tile.newData) { if (tile.newData) {
uploadTileData(tile); uploadTileData(tile);
continue; continue;
@ -1143,25 +1089,25 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
} }
if (GlUtils.checkGlOutOfMemory("upload: " + mBufferMemoryUsage) if (updateTextures > 0)
&& LIMIT_BUFFERS > MB) mTextRenderer.compileTextures();
LIMIT_BUFFERS -= MB;
// if (GlUtils.checkGlOutOfMemory("upload: " + mBufferMemoryUsage)
// && LIMIT_BUFFERS > MB)
// LIMIT_BUFFERS -= MB;
if (timing) if (timing)
clear_time = (SystemClock.uptimeMillis() - start); clear_time = (SystemClock.uptimeMillis() - start);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
glUseProgram(gPolygonProgram); glUseProgram(polygonProgram);
glEnableVertexAttribArray(gPolygonVertexPositionHandle); glEnableVertexAttribArray(hPolygonVertexPosition);
// if (!mTriangulate) {
glDisable(GL_BLEND); glDisable(GL_BLEND);
// Draw Polygons // Draw Polygons
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
// glEnableVertexAttribArray(gPolygonVertexPositionHandle);
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible) { if (tiles[i].isVisible) {
GLMapTile tile = tiles[i]; GLMapTile tile = tiles[i];
@ -1172,24 +1118,11 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
drawProxyPolygons(tile); drawProxyPolygons(tile);
} }
} }
// GlUtils.checkGlError("polygons");
glDisable(GL_STENCIL_TEST); 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...) // required on GalaxyII, Android 2.3.3 (cant just VAA enable once...)
glDisableVertexAttribArray(gPolygonVertexPositionHandle); glDisableVertexAttribArray(hPolygonVertexPosition);
if (timing) { if (timing) {
glFinish(); glFinish();
@ -1198,10 +1131,10 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// Draw lines // Draw lines
glEnable(GL_BLEND); glEnable(GL_BLEND);
glUseProgram(gLineProgram); glUseProgram(lineProgram);
glEnableVertexAttribArray(gLineVertexPositionHandle); glEnableVertexAttribArray(hLineVertexPosition);
glEnableVertexAttribArray(gLineTexturePositionHandle); glEnableVertexAttribArray(hLineTexturePosition);
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible) { 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) { if (timing) {
glFinish(); glFinish();
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start) + " " Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start) + " "
+ clear_time + " " + poly_time); + clear_time + " " + poly_time);
} }
glDisableVertexAttribArray(gLineVertexPositionHandle); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisableVertexAttribArray(gLineTexturePositionHandle);
// GlUtils.checkGlError("lines");
} }
private int[] mVboIds; private static TextRenderer mTextRenderer;
@Override @Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) { public void onSurfaceChanged(GL10 glUnused, int width, int height) {
GlUtils.checkGlError("onSurfaceChanged");
mVBOs.clear(); mVBOs.clear();
mTiles.clear(); mTiles.clear();
mTileList.clear(); mTileList.clear();
@ -1246,20 +1196,27 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mAspect = (float) height / width; mAspect = (float) height / width;
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
GlUtils.checkGlError("glViewport");
int tiles = (mWidth / Tile.TILE_SIZE + 4) * (mHeight / Tile.TILE_SIZE + 4); int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
curTiles = new TilesData(tiles); * (mHeight / (Tile.TILE_SIZE / 2) + 2);
newTiles = new TilesData(tiles);
nextTiles = new TilesData(tiles); curTiles = new TilesData(numTiles);
newTiles = new TilesData(numTiles);
nextTiles = new TilesData(numTiles);
// Set up vertex buffer objects // Set up vertex buffer objects
int numVBO = (CACHE_TILES + tiles) * 2; int numVBO = (CACHE_TILES + numTiles) * 2;
mVboIds = new int[numVBO]; int[] mVboIds = new int[numVBO];
glGenBuffers(numVBO, mVboIds, 0); glGenBuffers(numVBO, mVboIds, 0);
GlUtils.checkGlError("glGenBuffers");
for (int i = 0; i < numVBO; i++) for (int i = 0; i < numVBO; i++)
mVBOs.add(new VertexBufferObject(mVboIds[i])); mVBOs.add(new VertexBufferObject(mVboIds[i]));
// Set up textures
mTextRenderer = new TextRenderer(numTiles * 2);
mDebugSettings = mMapView.getDebugSettings(); mDebugSettings = mMapView.getDebugSettings();
mJobParameter = mMapView.getJobParameters(); mJobParameter = mMapView.getJobParameters();
@ -1273,14 +1230,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
public void onSurfaceCreated(GL10 gl, EGLConfig config) { public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Set up the program for rendering lines // Set up the program for rendering lines
gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader, lineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
Shaders.gLineFragmentShader); Shaders.gLineFragmentShader);
if (gLineProgram == 0) { if (lineProgram == 0) {
mSimpleLines = true; mSimpleLines = true;
Log.e(TAG, "trying simple line program."); Log.e(TAG, "trying simple line program.");
gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader, lineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
Shaders.gLineFragmentShaderSimple); Shaders.gLineFragmentShaderSimple);
if (gLineProgram == 0) { if (lineProgram == 0) {
Log.e(TAG, "Could not create line program."); Log.e(TAG, "Could not create line program.");
return; return;
} }
@ -1290,48 +1247,51 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (ext.indexOf("GL_OES_vertex_half_float") >= 0) { if (ext.indexOf("GL_OES_vertex_half_float") >= 0) {
useHalfFloat = true; useHalfFloat = true;
shortBuffer = new ShortBuffer[20]; shortBuffer = new ShortBuffer[rotateBuffers * 2];
} }
else { else {
floatBuffer = new FloatBuffer[20]; floatBuffer = new FloatBuffer[rotateBuffers * 2];
} }
Log.d(TAG, "Extensions: " + ext); Log.d(TAG, "Extensions: " + ext);
gLineMatrixHandle = glGetUniformLocation(gLineProgram, "u_center"); hLineMatrix = glGetUniformLocation(lineProgram, "u_center");
gLineModeHandle = glGetUniformLocation(gLineProgram, "u_mode"); hLineMode = glGetUniformLocation(lineProgram, "u_mode");
gLineColorHandle = glGetUniformLocation(gLineProgram, "u_color"); hLineColor = glGetUniformLocation(lineProgram, "u_color");
gLineVertexPositionHandle = GLES20 hLineVertexPosition = GLES20.glGetAttribLocation(lineProgram, "a_position");
.glGetAttribLocation(gLineProgram, "a_position"); hLineTexturePosition = glGetAttribLocation(lineProgram, "a_st");
gLineTexturePositionHandle = glGetAttribLocation(gLineProgram, "a_st");
if (mSimpleLines) if (mSimpleLines)
gLineWidthHandle = glGetUniformLocation(gLineProgram, "u_width"); hLineWidth = glGetUniformLocation(lineProgram, "u_width");
// Set up the program for rendering polygons // Set up the program for rendering polygons
gPolygonProgram = GlUtils.createProgram(Shaders.gPolygonVertexShader, polygonProgram = GlUtils.createProgram(Shaders.gPolygonVertexShader,
Shaders.gPolygonFragmentShader); Shaders.gPolygonFragmentShader);
if (gPolygonProgram == 0) { if (polygonProgram == 0) {
Log.e(TAG, "Could not create polygon program."); Log.e(TAG, "Could not create polygon program.");
return; return;
} }
gPolygonMatrixHandle = glGetUniformLocation(gPolygonProgram, "u_center"); hPolygonMatrix = glGetUniformLocation(polygonProgram, "u_center");
gPolygonVertexPositionHandle = glGetAttribLocation(gPolygonProgram, hPolygonVertexPosition = glGetAttribLocation(polygonProgram, "a_position");
"a_position"); hPolygonColor = glGetUniformLocation(polygonProgram, "u_color");
gPolygonColorHandle = glGetUniformLocation(gPolygonProgram, "u_color");
// glUseProgram(gPolygonProgram); // glUseProgram(polygonProgram);
// glEnableVertexAttribArray(gPolygonVertexPositionHandle); // glEnableVertexAttribArray(hPolygonVertexPosition);
// //
// glUseProgram(gLineProgram); // glUseProgram(lineProgram);
// glEnableVertexAttribArray(gLineVertexPositionHandle); // glEnableVertexAttribArray(hLineVertexPosition);
// glEnableVertexAttribArray(gLineTexturePositionHandle); // glEnableVertexAttribArray(hLineTexturePosition);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthMask(false); glDepthMask(false);
glDisable(GL_DITHER); glDisable(GL_DITHER);
glClearColor(0.98f, 0.98f, 0.97f, 1.0f); glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
glClearStencil(0); glClearStencil(0);
GlUtils.checkGlError("onSurfaceCreated");
} }
private void drawProxyLines(GLMapTile tile) { 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 @Override
public boolean processedTile() { public boolean processedTile() {
return true; return true;

View File

@ -14,21 +14,21 @@
*/ */
package org.mapsforge.android.glrenderer; package org.mapsforge.android.glrenderer;
import java.util.LinkedList; import org.mapsforge.android.rendertheme.renderinstruction.Area;
class PolygonLayer extends Layer { class PolygonLayer extends Layer {
int fadeLevel; PolygonLayer next;
Area area;
private boolean first = true; private boolean first = true;
private float originX; private float originX;
private float originY; private float originY;
PolygonLayer(int layer, int color, int fade) { PolygonLayer(int layer, Area area) {
super(layer, color); super(layer);
fadeLevel = fade; this.area = area;
curItem = LayerPool.get(); curItem = VertexPool.get();
pool = new LinkedList<PoolItem>(); pool = curItem;
pool.add(curItem);
} }
void addPolygon(float[] points, int pos, int length) { 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.android.utils.FastMath;
import org.mapsforge.core.Tile; import org.mapsforge.core.Tile;
import android.util.SparseArray;
class PolygonLayers { class PolygonLayers {
private static final int NUM_VERTEX_FLOATS = 2; 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, Tile.TILE_SIZE + 1, Tile.TILE_SIZE + 1, -2,
-2, Tile.TILE_SIZE + 1, -2 }; -2, Tile.TILE_SIZE + 1, -2 };
private static short[] mByteFillCoords = null; private static short[] mByteFillCoords = null;
private SparseArray<PolygonLayer> layers; static FloatBuffer compileLayerData(PolygonLayer layers, FloatBuffer buf) {
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) {
FloatBuffer fbuf = buf; FloatBuffer fbuf = buf;
int size = 4;
array = new PolygonLayer[layers.size()]; for (PolygonLayer l = layers; l != null; l = l.next)
for (int i = 0, n = layers.size(); i < n; i++) {
PolygonLayer l = layers.valueAt(i);
array[i] = l;
size += l.verticesCnt; size += l.verticesCnt;
}
size *= NUM_VERTEX_FLOATS; size *= NUM_VERTEX_FLOATS;
@ -81,38 +51,40 @@ class PolygonLayers {
fbuf.put(mFillCoords, 0, 8); fbuf.put(mFillCoords, 0, 8);
int pos = 4; int pos = 4;
for (int i = 0, n = array.length; i < n; i++) { PoolItem last = null, items = null;
PolygonLayer l = array[i];
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); fbuf.put(item.vertices, 0, item.used);
last = item;
} }
l.offset = pos; l.offset = pos;
pos += l.verticesCnt; pos += l.verticesCnt;
LayerPool.add(l.pool); if (last != null) {
last.next = items;
items = l.pool;
}
l.pool = null; l.pool = null;
} }
fbuf.flip(); VertexPool.add(items);
// not needed for drawing fbuf.flip();
layers = null;
return fbuf; return fbuf;
} }
ShortBuffer compileLayerData(ShortBuffer buf) { static final short[] tmpItem = new short[PoolItem.SIZE];
static ShortBuffer compileLayerData(PolygonLayer layers, ShortBuffer buf) {
ShortBuffer sbuf = buf; ShortBuffer sbuf = buf;
int size = 4;
array = new PolygonLayer[layers.size()]; for (PolygonLayer l = layers; l != null; l = l.next)
for (int i = 0, n = layers.size(); i < n; i++) {
PolygonLayer l = layers.valueAt(i);
array[i] = l;
size += l.verticesCnt; size += l.verticesCnt;
}
size *= NUM_VERTEX_FLOATS; size *= NUM_VERTEX_FLOATS;
@ -124,7 +96,7 @@ class PolygonLayers {
sbuf.clear(); sbuf.clear();
} }
short[] data = new short[PoolItem.SIZE]; short[] data = tmpItem;
if (mByteFillCoords == null) { if (mByteFillCoords == null) {
mByteFillCoords = new short[8]; mByteFillCoords = new short[8];
@ -141,27 +113,38 @@ class PolygonLayers {
sbuf.put(mByteFillCoords, 0, 8); sbuf.put(mByteFillCoords, 0, 8);
int pos = 4; int pos = 4;
for (int i = 0, n = array.length; i < n; i++) { PoolItem last = null, items = null;
PolygonLayer l = array[i];
for (int k = 0, m = l.pool.size(); k < m; k++) { for (PolygonLayer l = layers; l != null; l = l.next) {
PoolItem item = l.pool.get(k);
for (PoolItem item = l.pool; item != null; item = item.next) {
PoolItem.toHalfFloat(item, data); PoolItem.toHalfFloat(item, data);
sbuf.put(data, 0, item.used); sbuf.put(data, 0, item.used);
last = item;
} }
l.offset = pos; l.offset = pos;
pos += l.verticesCnt; pos += l.verticesCnt;
LayerPool.add(l.pool); if (last != null) {
last.next = items;
items = l.pool;
}
l.pool = null; l.pool = null;
} }
sbuf.flip(); VertexPool.add(items);
// not needed for drawing sbuf.flip();
layers = null;
return sbuf; 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 { class PoolItem {
final float[] vertices; final float[] vertices;
int used; int used;
PoolItem next;
PoolItem() { PoolItem() {
vertices = new float[SIZE]; vertices = new float[SIZE];
used = 0; 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_PREC = 5.96046E-8f;
private static final float FLOAT_HALF_MAX = 65504f; private static final float FLOAT_HALF_MAX = 65504f;

View File

@ -23,6 +23,8 @@ class Shaders {
+ "attribute vec2 a_st;" + "attribute vec2 a_st;"
+ "varying vec2 v_st;" + "varying vec2 v_st;"
+ "void main() {" + "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;" + " gl_Position = u_center * a_position;"
+ " v_st = a_st;" + " 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; package org.mapsforge.android.glrenderer;
import java.util.LinkedList; import android.annotation.SuppressLint;
class LayerPool { class VertexPool {
static private LinkedList<PoolItem> pool = null; private static final int POOL_LIMIT = 8192;
static private int count;
@SuppressLint("UseValueOf")
private static final Boolean lock = new Boolean(true);
static private PoolItem pool = null;
static private int count = 0;
static void init() { static void init() {
if (pool == null) {
pool = new LinkedList<PoolItem>();
count = 0;
}
} }
static PoolItem get() { static PoolItem get() {
synchronized (pool) { synchronized (lock) {
if (count == 0) if (count == 0)
return new PoolItem(); return new PoolItem();
count--; count--;
PoolItem it = pool.pop();
PoolItem it = pool;
pool = pool.next;
it.used = 0; it.used = 0;
it.next = null;
return it; return it;
} }
} }
static void add(LinkedList<PoolItem> items) { static void add(PoolItem items) {
synchronized (pool) { if (items == null)
int size = items.size(); 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++; 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.content.Context;
import android.os.CountDownTimer; import android.os.CountDownTimer;
import android.os.SystemClock;
import android.util.Log; import android.util.Log;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener; import android.view.GestureDetector.SimpleOnGestureListener;
@ -59,7 +60,8 @@ public class TouchHandler {
mMapView = mapView; mMapView = mapView;
mMapMoveDelta = viewConfiguration.getScaledTouchSlop(); mMapMoveDelta = viewConfiguration.getScaledTouchSlop();
mActivePointerId = INVALID_POINTER_ID; mActivePointerId = INVALID_POINTER_ID;
mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener(mMapView)); mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener(
mMapView));
mGestureDetector = new GestureDetector(new MapGestureDetector(mMapView)); mGestureDetector = new GestureDetector(new MapGestureDetector(mMapView));
} }
@ -90,7 +92,8 @@ public class TouchHandler {
boolean scaling = mScaleGestureDetector.isInProgress(); boolean scaling = mScaleGestureDetector.isInProgress();
if (!scaling && !mMoveThresholdReached) { 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 // the map movement threshold has been reached
// longPressDetector.pressStop(); // longPressDetector.pressStop();
mMoveThresholdReached = true; mMoveThresholdReached = true;
@ -179,15 +182,19 @@ public class TouchHandler {
return true; return true;
} }
private long lastRun = 0;
/** /**
* @param motionEvent * @param motionEvent
* ... * ...
* @return ... * @return ...
*/ */
public boolean handleMotionEvent(MotionEvent motionEvent) { public boolean handleMotionEvent(MotionEvent motionEvent) {
// workaround for a bug in the ScaleGestureDetector, see Android issue // workaround for a bug in the ScaleGestureDetector, see Android issue
// #12976 // #12976
if (motionEvent.getAction() != MotionEvent.ACTION_MOVE || motionEvent.getPointerCount() > 1) { if (motionEvent.getAction() != MotionEvent.ACTION_MOVE
|| motionEvent.getPointerCount() > 1) {
mScaleGestureDetector.onTouchEvent(motionEvent); mScaleGestureDetector.onTouchEvent(motionEvent);
} }
@ -197,23 +204,44 @@ public class TouchHandler {
// // return true; // // return true;
// } // }
int action = getAction(motionEvent); int action = getAction(motionEvent);
boolean ret = false;
if (action == MotionEvent.ACTION_DOWN) { if (action == MotionEvent.ACTION_DOWN) {
return onActionDown(motionEvent); ret = onActionDown(motionEvent);
} else if (action == MotionEvent.ACTION_MOVE) { } else if (action == MotionEvent.ACTION_MOVE) {
return onActionMove(motionEvent); ret = onActionMove(motionEvent);
} else if (action == MotionEvent.ACTION_UP) { } else if (action == MotionEvent.ACTION_UP) {
return onActionUp(motionEvent); ret = onActionUp(motionEvent);
} else if (action == MotionEvent.ACTION_CANCEL) { } else if (action == MotionEvent.ACTION_CANCEL) {
return onActionCancel(); ret = onActionCancel();
// } else if (action == MotionEvent.ACTION_POINTER_DOWN) { // } else if (action == MotionEvent.ACTION_POINTER_DOWN) {
// return onActionPointerDown(motionEvent); // return onActionPointerDown(motionEvent);
} else if (action == MotionEvent.ACTION_POINTER_UP) { } 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 // the event was not handled
return false; return ret;
} }
class MapGestureDetector extends SimpleOnGestureListener { class MapGestureDetector extends SimpleOnGestureListener {
@ -254,7 +282,8 @@ public class TouchHandler {
} }
@Override @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 w = Tile.TILE_SIZE * 20;
int h = Tile.TILE_SIZE * 20; int h = Tile.TILE_SIZE * 20;
mPrevX = 0; mPrevX = 0;
@ -265,7 +294,8 @@ public class TouchHandler {
mTimer = null; 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 // animate for two seconds
mTimer = new CountDownTimer(2000, 20) { mTimer = new CountDownTimer(2000, 20) {
@Override @Override

View File

@ -15,6 +15,7 @@
package org.mapsforge.android.rendertheme; package org.mapsforge.android.rendertheme;
import org.mapsforge.android.rendertheme.renderinstruction.Area; 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.Line;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -37,14 +38,8 @@ public interface IRenderCallback {
* *
* @param caption * @param caption
* the text to be rendered. * 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. * Renders an area symbol with the given bitmap.
@ -59,14 +54,8 @@ public interface IRenderCallback {
* *
* @param caption * @param caption
* the text to be rendered. * 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. * 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) { public void matchNode(IRenderCallback renderCallback, Tag[] tags, byte zoomLevel) {
// List<RenderInstruction> matchingList = matchingListNode; // List<RenderInstruction> matchingList = matchingListNode;
// MatchingCacheKey matchingCacheKey = matchingCacheKeyNode; // MatchingCacheKey matchingCacheKey = matchingCacheKeyNode;
//
// if (!changed) { // if (!changed) {
// if (matchingList != null) { // if (matchingList != null) {
// for (int i = 0, n = matchingList.size(); i < n; ++i) { // for (int i = 0, n = matchingList.size(); i < n; ++i) {
@ -158,11 +158,13 @@ public class RenderTheme {
// matchingList.get(i).renderNode(renderCallback, tags); // matchingList.get(i).renderNode(renderCallback, tags);
// } // }
// } else { // } else {
// // cache miss
// cache miss
// matchingList = new ArrayList<RenderInstruction>(); // matchingList = new ArrayList<RenderInstruction>();
// for (int i = 0, n = mRulesList.size(); i < n; ++i) { for (int i = 0, n = mRulesList.size(); i < n; ++i) {
// mRulesList.get(i).matchNode(renderCallback, tags, zoomLevel, matchingList); mRulesList.get(i).matchNode(renderCallback, tags, zoomLevel);
// } // , matchingList
}
// matchingCacheNodes.put(matchingCacheKey, matchingList); // matchingCacheNodes.put(matchingCacheKey, matchingList);
// } // }
// //
@ -214,7 +216,7 @@ public class RenderTheme {
public synchronized RenderInstruction[] matchWay(IRenderCallback renderCallback, public synchronized RenderInstruction[] matchWay(IRenderCallback renderCallback,
Tag[] tags, Tag[] tags,
byte zoomLevel, byte zoomLevel,
boolean closed, boolean changed) { boolean closed, boolean render) {
RenderInstruction[] renderInstructions = null; RenderInstruction[] renderInstructions = null;
LRUCache<MatchingCacheKey, RenderInstruction[]> matchingCache; LRUCache<MatchingCacheKey, RenderInstruction[]> matchingCache;
@ -240,12 +242,6 @@ public class RenderTheme {
boolean found = matchingCache.containsKey(matchingCacheKey); boolean found = matchingCache.containsKey(matchingCacheKey);
if (found) { if (found) {
renderInstructions = matchingCache.get(matchingCacheKey); renderInstructions = matchingCache.get(matchingCacheKey);
if (renderInstructions != null) {
for (int i = 0, n = renderInstructions.length; i < n; i++)
renderInstructions[i].renderWay(renderCallback, tags);
}
} else { } else {
// cache miss // cache miss
int c = (closed ? Closed.YES : Closed.NO); int c = (closed ? Closed.YES : Closed.NO);
@ -259,13 +255,17 @@ public class RenderTheme {
renderInstructions = new RenderInstruction[matchingList.size()]; renderInstructions = new RenderInstruction[matchingList.size()];
for (int i = 0, n = matchingList.size(); i < n; ++i) { for (int i = 0, n = matchingList.size(); i < n; ++i) {
RenderInstruction renderInstruction = matchingList.get(i); RenderInstruction renderInstruction = matchingList.get(i);
renderInstruction.renderWay(renderCallback, tags);
renderInstructions[i] = renderInstruction; renderInstructions[i] = renderInstruction;
} }
} }
matchingCache.put(matchingCacheKey, renderInstructions); 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; // mRenderInstructions = renderInstructions;
return renderInstructions; return renderInstructions;
} }

View File

@ -5,29 +5,36 @@
version="1" map-background="#f0f0f0"> version="1" map-background="#f0f0f0">
<!-- ways --> <!-- 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="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" /> <area fill="#fff8bf" fade="10" />
</rule> </rule>
<!-- Steinbruch, Schotter-, Kies-, Sand- und Tongrube -->
<rule e="way" k="landuse" v="grass"> <rule e="way" k="*" v="quarry">
<area fill="#deecb9" fade="10" /> <area fill="#ddddcc" fade="10" />
</rule> </rule>
<rule e="way" k="*" v="residential|farmyard|retail|commercial"> <rule e="way" k="*" v="residential|farmyard|retail|commercial">
<area fill="#efefeb" fade="10" /> <area fill="#efefeb" fade="10" />
</rule> </rule>
<!-- <rule e="way" k="landuse" v="industrial|brownfield|railway"> <area <rule e="way" k="*" v="industrial|railway"> <area
fill="#bcaacd" stroke="#e4e4e4" stroke-width="0.2" /> --> fill="#e8e3e4" stroke="#e4e4e4" stroke-width="0.2" fade="10" />
</rule>
<!--<rule e="way" k="landuse" v="construction|greenfield"> <area fill="#a47c41" <!--<rule e="way" k="landuse" v="construction|greenfield"> <area fill="#a47c41"
stroke="#e4e4e4" stroke-width="0.2" /> </rule> --> stroke="#e4e4e4" stroke-width="0.2" /> </rule> -->
<!-- <rule e="way" k="landuse" v="garages"> <area fill="#d6d6e4" /> </rule> --> <!-- <rule e="way" k="landuse" v="garages"> <area fill="#d6d6e4" /> </rule> -->
</rule> </rule>
<rule e="way" k="outline" v="*"> <rule e="way" k="outline" v="*">
@ -99,15 +106,16 @@
</rule> </rule>
</rule> </rule>
</rule> </rule>
<!-- landuse --> <!-- 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" <!-- <rule e="way" k="*" v="landfill|quarry"> <area fill="#e9dd72" stroke="#556b2f"
stroke-width="0.2" /> </rule> --> stroke-width="0.2" /> </rule> -->
<rule e="way" k="*" v="cemetery"> <rule e="way" k="*" v="cemetery">
<area fill="#d7e6b0" /> <area fill="#d7e6b0" />
</rule> </rule>
<rule e="way" k="*" v="meadow|scrub"> <rule e="way" k="*" v="meadow">
<area fill="#deecb9" /> <area fill="#ebf2d2" fade="10"/>
</rule> </rule>
<!-- <rule e="way" k="*" v="village_green|recreation_ground"> <!-- <rule e="way" k="*" v="village_green|recreation_ground">
@ -122,7 +130,12 @@
</rule> </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" /> <area fill="#e7f7c1" fade="12" />
</rule> </rule>
@ -132,19 +145,35 @@
<area fill="#d7e6b0" fade="12" /> <area fill="#d7e6b0" fade="12" />
</rule> </rule>
</rule> </rule>
<rule e="way" k="natural|landuse" v="forest|wood" zoom-min="9"> <rule e="way" k="natural|" v="*">
<!-- <area fill="#BCCBB0" fade="10" /> --> <rule e="way" k="*" v="wood">
<!-- <rule e="way" k="*" v="*" zoom-max="11"> --> <rule e="way" k="*" v="*" zoom-max="12">
<area fill="#d3dec8" fade="9" /> <area fill="#ebefe5" fade="7" />
<!-- </rule> --> </rule>
<!-- <rule e="way" k="*" v="*" zoom-min="12"> <rule e="way" k="*" v="*" zoom-min="11">
<area fill="#cde2bc" fade="12" /> <area fill="#d3dec8" fade="12" />
</rule> --> </rule>
<!-- <area fill="#87a670" fade="10" /> --> </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 --> <!-- amenity -->
<rule e="way" k="amenity" v="*"> <rule e="way" k="amenity" v="*">
@ -181,7 +210,7 @@
<rule e="way" k="*" zoom-min="12" v="heath"> <rule e="way" k="*" zoom-min="12" v="heath">
<area fill="#ffffc0" fade="12" /> <area fill="#ffffc0" fade="12" />
</rule> </rule>
<rule e="way" k="*" v="marsh|wetland"> <rule e="way" k="*" v="marsh|wetland|mud">
<area fill="#deecb9" fade="12" /> <area fill="#deecb9" fade="12" />
</rule> </rule>
</rule> </rule>
@ -190,14 +219,23 @@
<!-- leisure --> <!-- leisure -->
<rule e="way" k="leisure" v="*" zoom-min="13"> <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 --> <!-- 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" /> <area fill="#daefdb" fade="12" />
</rule> </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"> <rule e="way" k="*" v="playing_fields|pitch">
<area fill="#f4f4de" /> <area fill="#f4f4de" />
<line stroke="#dbdbc8" stroke-width="0.6" fixed="true" <line stroke="#dbdbc8" stroke-width="0.6" fixed="true"
@ -235,10 +273,10 @@
<line stroke="#b4cbdc" stroke-width="0.275" stroke-linecap="butt" /> <line stroke="#b4cbdc" stroke-width="0.275" stroke-linecap="butt" />
</rule> </rule>
<rule e="way" k="waterway" v="river" zoom-min="12"> <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>
<rule e="way" k="waterway" v="river" zoom-max="11"> <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" /> fixed="true" />
</rule> </rule>
<rule e="way" k="waterway" v="riverbank|dock"> <rule e="way" k="waterway" v="riverbank|dock">
@ -346,6 +384,8 @@
</rule> --> </rule> -->
</rule> </rule>
<rule e="way" k="outline" v="*"> <rule e="way" k="outline" v="*">
<rule e="way" k="*" v="1"> <rule e="way" k="*" v="1">
<outline stroke="#909090" /> <outline stroke="#909090" />
@ -371,30 +411,30 @@
<rule e="way" k="*" v="secondary|primary_link" zoom-min="9"> <rule e="way" k="*" v="secondary|primary_link" zoom-min="9">
<!-- <line stroke="#eeee4a" stroke-width="1.8" stroke-linecap="butt" <!-- <line stroke="#eeee4a" stroke-width="1.8" stroke-linecap="butt"
fixed="true" /> --> fixed="true" /> -->
<line stroke="#f2df6d" stroke-width="1.9" stroke-linecap="butt" <line stroke="#f2df6d" stroke-width="1.8" stroke-linecap="butt"
fixed="true" /> fixed="true" fade="9"/>
</rule> </rule>
<rule e="way" k="*" v="trunk_link|motorway_link" zoom-min="8"> <rule e="way" k="*" v="trunk_link|motorway_link" zoom-min="8">
<line stroke="#fed6a3" stroke-width="2.0" stroke-linecap="butt" <line stroke="#fed6a3" stroke-width="1.8" stroke-linecap="butt"
fixed="true" /> fixed="true" fade="8"/>
</rule> </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" <!-- <line stroke="#eeee4a" stroke-width="1.4" stroke-linecap="butt"
fixed="true" /> --> fixed="true" /> -->
<line stroke="#f2df6d" stroke-width="2.0" stroke-linecap="butt" <line stroke="#f2df6d" stroke-width="1.8" stroke-linecap="butt"
fixed="true" /> fixed="true" fade="5"/>
</rule> </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" <line stroke="#fed6a3" stroke-width="2.0" stroke-linecap="butt"
fixed="true" /> fixed="true" fade="5"/>
</rule> </rule>
<rule e="way" k="*" v="motorway"> <rule e="way" k="*" v="motorway">
<line stroke="#eec693" stroke-width="2.4" stroke-linecap="butt" <line stroke="#eec693" stroke-width="2.2" stroke-linecap="butt"
fixed="true" /> fixed="true" fade="4"/>
</rule> </rule>
</rule> </rule>
@ -403,11 +443,11 @@
<rule e="way" k="*" v="*" zoom-min="15"> <rule e="way" k="*" v="*" zoom-min="15">
<rule e="way" k="*" v="steps"> <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" /> stroke-linecap="butt" />
</rule> </rule>
<rule e="way" k="*" v="track|footway|path|cycleway" zoom-min="16"> <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>
</rule> </rule>
@ -426,7 +466,7 @@
</rule> </rule>
<rule e="way" k="*" v="construction"> <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>
</rule> </rule>
@ -434,10 +474,10 @@
<rule e="way" k="*" v="residential|road|unclassified|living_street"> <rule e="way" k="*" v="residential|road|unclassified|living_street">
<rule e="way" k="bridge" v="yes|true"> <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>
<rule e="way" k="bridge" v="~|no|false"> <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>
</rule> </rule>
@ -558,11 +598,11 @@
</rule> </rule>
<!-- railway casings and cores --> <!-- 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" /> <line stroke="#8c8f8c" stroke-width="0.8" fixed="true" />
</rule> </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" <line stroke="#a0a0a0" stroke-width="0.8" stroke-linecap="butt"
fixed="true" /> fixed="true" />
@ -579,6 +619,12 @@
<line stroke="#bbbbcc" stroke-width="0.6" stroke-linecap="butt" <line stroke="#bbbbcc" stroke-width="0.6" stroke-linecap="butt"
fixed="true" /> fixed="true" />
</rule> </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>
</rule> </rule>
@ -634,6 +680,15 @@
<caption k="name" font-style="bold" font-size="10" fill="#000000" <caption k="name" font-style="bold" font-size="10" fill="#000000"
stroke="#ffffff" stroke-width="2.0" /> stroke="#ffffff" stroke-width="2.0" />
</rule> </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>
<rule e="node" k="*" v="*"> <rule e="node" k="*" v="*">
@ -642,6 +697,10 @@
<circle r="1.5" fill="#909090" /> <circle r="1.5" fill="#909090" />
</rule> </rule>
<rule e="node" k="debug" v="*" >
<caption k="name" font-size="12" fill="#0000ff" />
</rule>
<!-- highway --> <!-- highway -->
<!-- <rule e="node" k="highway" v="*"> <rule e="node" k="highway" v="turning_circle"> <!-- <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" <caption k="name" font-style="bold" font-size="20" fill="#000000"
stroke="#ffffff" stroke-width="2.0" /> stroke="#ffffff" stroke-width="2.0" />
</rule> </rule>
<rule e="node" k="*" v="city" zoom-max="14"> <rule e="node" k="*" v="city">
<caption k="name" font-style="bold" font-size="25" fill="#000000" <caption k="name" font-style="bold" font-size="20" fill="#000000"
stroke="#ffffff" stroke-width="2.0" /> stroke="#ffffff" stroke-width="2.0" />
</rule> </rule>
<rule e="node" k="*" v="country" zoom-max="6"> <rule e="node" k="*" v="country" zoom-max="7">
<caption k="name" font-style="bold" font-size="25" fill="#000000" <caption k="name" font-size="20" fill="#000000"
stroke="#ffffff" stroke-width="2.0" /> stroke="#ffffff" stroke-width="2.0" />
</rule> </rule>
</rule> </rule>

View File

@ -42,7 +42,8 @@ public final class Area implements RenderInstruction {
* @throws IOException * @throws IOException
* if an I/O error occurs while reading a resource. * 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; String src = null;
int fill = Color.BLACK; int fill = Color.BLACK;
int stroke = Color.TRANSPARENT; int stroke = Color.TRANSPARENT;
@ -73,7 +74,8 @@ public final class Area implements RenderInstruction {
private static void validate(float strokeWidth) { private static void validate(float strokeWidth) {
if (strokeWidth < 0) { 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; 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(); super();
Shader shader = BitmapUtils.createBitmapShader(src);
if (fill == Color.TRANSPARENT) { if (fill == Color.TRANSPARENT) {
paintFill = null; paintFill = null;
} else { } else {
paintFill = new Paint(Paint.ANTI_ALIAS_FLAG); 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.setStyle(Style.FILL);
paintFill.setColor(fill); paintFill.setColor(fill);
paintFill.setStrokeCap(Cap.ROUND); paintFill.setStrokeCap(Cap.ROUND);
@ -125,7 +129,12 @@ public final class Area implements RenderInstruction {
paintOutline.setColor(stroke); paintOutline.setColor(stroke);
paintOutline.setStrokeCap(Cap.ROUND); 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.strokeWidth = strokeWidth;
this.fade = fade; this.fade = fade;
this.level = level; this.level = level;

View File

@ -24,8 +24,10 @@ import org.xml.sax.Attributes;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Paint.Align; import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.util.FloatMath;
/** /**
* Represents a text label on the map. * 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); 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) { 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) { } 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) { } 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; public final float dy;
private final float mFontSize; public float fontSize;
private final Paint mPaint; public final Paint paint;
private final Paint mStroke; public final Paint stroke;
private final String mTextKey; 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(); super();
mTextKey = textKey; this.textKey = textKey.intern();
mDy = dy; this.dy = dy;
this.fontSize = fontSize;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); paint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setTextAlign(Align.LEFT); paint.setTextAlign(Align.CENTER);
mPaint.setTypeface(typeface); paint.setTypeface(typeface);
mPaint.setColor(fill); paint.setColor(fillColor);
mStroke = new Paint(Paint.ANTI_ALIAS_FLAG); stroke = new Paint(Paint.ANTI_ALIAS_FLAG);
mStroke.setStyle(Style.STROKE); stroke.setStyle(Style.STROKE);
mStroke.setTextAlign(Align.LEFT); stroke.setTextAlign(Align.CENTER);
mStroke.setTypeface(typeface); stroke.setTypeface(typeface);
mStroke.setColor(stroke); stroke.setColor(strokeColor);
mStroke.setStrokeWidth(strokeWidth); 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 @Override
@ -122,12 +137,12 @@ public final class Caption implements RenderInstruction {
@Override @Override
public void renderNode(IRenderCallback renderCallback, Tag[] tags) { public void renderNode(IRenderCallback renderCallback, Tag[] tags) {
renderCallback.renderPointOfInterestCaption(mTextKey, mDy, mPaint, mStroke); renderCallback.renderPointOfInterestCaption(this);
} }
@Override @Override
public void renderWay(IRenderCallback renderCallback, Tag[] tags) { public void renderWay(IRenderCallback renderCallback, Tag[] tags) {
renderCallback.renderAreaCaption(mTextKey, mDy, mPaint, mStroke); renderCallback.renderAreaCaption(this);
} }
@Override @Override
@ -137,7 +152,7 @@ public final class Caption implements RenderInstruction {
@Override @Override
public void scaleTextSize(float scaleFactor) { public void scaleTextSize(float scaleFactor) {
mPaint.setTextSize(mFontSize * scaleFactor); paint.setTextSize(fontSize * scaleFactor);
mStroke.setTextSize(mFontSize * scaleFactor); stroke.setTextSize(fontSize * scaleFactor);
} }
} }

View File

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

View File

@ -22,6 +22,7 @@ import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.rendertheme.IRenderCallback; import org.mapsforge.android.rendertheme.IRenderCallback;
import org.mapsforge.android.rendertheme.RenderTheme; import org.mapsforge.android.rendertheme.RenderTheme;
import org.mapsforge.android.rendertheme.renderinstruction.Area; 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.Line;
import org.mapsforge.core.Tag; import org.mapsforge.core.Tag;
import org.mapsforge.core.Tile; import org.mapsforge.core.Tile;
@ -218,8 +219,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
} }
@Override @Override
public void renderAreaCaption(String textKey, float verticalOffset, Paint paint, public void renderAreaCaption(Caption caption) {
Paint stroke) {
// mapDatabase.readTag(caption); // mapDatabase.readTag(caption);
// if (caption.value != null) { // if (caption.value != null) {
// float[] centerPosition = GeometryUtils // float[] centerPosition = GeometryUtils
@ -241,7 +241,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
} }
@Override @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)]; mDrawingLayer = mWays[getValidLayer(layer)];
mPoiX = scaleLongitude(longitude); mPoiX = scaleLongitude(longitude);
mPoiY = scaleLatitude(latitude); mPoiY = scaleLatitude(latitude);
@ -249,8 +250,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
} }
@Override @Override
public void renderPointOfInterestCaption(String textKey, float verticalOffset, public void renderPointOfInterestCaption(Caption caption) {
Paint paint, Paint stroke) {
// mapDatabase.readTag(caption); // mapDatabase.readTag(caption);
// if (caption.value != null) { // if (caption.value != null) {
// nodes.add(new PointTextContainer(caption.value, poiX, poiY + verticalOffset, paint, stroke)); // 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; // private byte mPrevLayer = 0;
@Override @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) { boolean changed) {
// if (mCoords == null) // if (mCoords == null)
// mCoords = mMapDatabase.getCoordinates(); // mCoords = mMapDatabase.getCoordinates();
@ -526,4 +526,10 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
// TODO Auto-generated method stub // 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(); int program = GLES20.glCreateProgram();
if (program != 0) { if (program != 0) {
checkGlError("glCreateProgram");
GLES20.glAttachShader(program, vertexShader); GLES20.glAttachShader(program, vertexShader);
checkGlError("glAttachShader"); checkGlError("glAttachShader");
GLES20.glAttachShader(program, pixelShader); GLES20.glAttachShader(program, pixelShader);

View File

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

View File

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

View File

@ -27,7 +27,7 @@ public class Tile {
/** /**
* Width and height of a map tile in pixel. * 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. * Size of a single uncompressed map tile bitmap in bytes.

View File

@ -36,8 +36,10 @@ public interface IMapDatabase {
* the tile to read. * the tile to read.
* @param mapDatabaseCallback * @param mapDatabaseCallback
* the callback which handles the extracted map elements. * 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. * @return the metadata for the current map file.

View File

@ -33,7 +33,7 @@ public interface IMapDatabaseCallback {
* @param tags * @param tags
* the tags of the node. * 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. * Renders water background for the current tile.
@ -54,5 +54,9 @@ public interface IMapDatabaseCallback {
* @param changed * @param changed
* tags have changed since last call (just an optional hint) * 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.IMapDatabase;
import org.mapsforge.database.IMapDatabaseCallback; import org.mapsforge.database.IMapDatabaseCallback;
import org.mapsforge.database.MapFileInfo; 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 final static String PROJECTION = "Mercator";
private float[] mCoords = new float[20]; 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("boundary", "administrative"), new Tag("admin_level", "2") };
private Tag[] mTags = { new Tag("natural", "water") }; private Tag[] mTags = { new Tag("natural", "water") };
private Tag[] mNameTags;
private final MapFileInfo mMapInfo = private final MapFileInfo mMapInfo =
new MapFileInfo(new BoundingBox(-180, -90, 180, 90), new MapFileInfo(new BoundingBox(-180, -90, 180, 90),
new Byte((byte) 0), null, PROJECTION, 0, 0, 0, "de", "yo!", "by me"); 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; // private static double HALF_PI = Math.PI / 2;
@Override @Override
public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) { public QueryResult executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
long cx = tile.pixelX + (Tile.TILE_SIZE >> 1); long cx = tile.pixelX + (Tile.TILE_SIZE >> 1);
long cy = tile.pixelY + (Tile.TILE_SIZE >> 1); long cy = tile.pixelY + (Tile.TILE_SIZE >> 1);
@ -140,6 +143,17 @@ public class MapDatabase implements IMapDatabase {
mIndex[1] = 10; mIndex[1] = 10;
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, mIndex, true); 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 @Override

View File

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

View File

@ -46,6 +46,7 @@ import org.mapsforge.database.FileOpenResult;
import org.mapsforge.database.IMapDatabase; import org.mapsforge.database.IMapDatabase;
import org.mapsforge.database.IMapDatabaseCallback; import org.mapsforge.database.IMapDatabaseCallback;
import org.mapsforge.database.MapFileInfo; import org.mapsforge.database.MapFileInfo;
import org.mapsforge.database.QueryResult;
import android.util.Log; 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: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/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 = private static final Header encodingHeader =
new BasicHeader("Accept-Encoding", "gzip"); new BasicHeader("Accept-Encoding", "gzip");
private static volatile HashMap<String, Tag> tagHash = new HashMap<String, Tag>(100); 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 int mCurTagCnt;
// private AndroidHttpClient mClient;
private HttpClient mClient; private HttpClient mClient;
private IMapDatabaseCallback mMapGenerator; private IMapDatabaseCallback mMapGenerator;
private float mScaleFactor; private float mScaleFactor;
private HttpGet mRequest = null;
@Override @Override
public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) { public QueryResult executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
mCanceled = false; mCanceled = false;
// Log.d(TAG, "get tile >> : " + tile);
if (mClient == null)
createClient();
String url = String.format(URL, Integer.valueOf(tile.zoomLevel), String url = String.format(URL, Integer.valueOf(tile.zoomLevel),
Long.valueOf(tile.tileX), Long.valueOf(tile.tileY)); Long.valueOf(tile.tileX), Long.valueOf(tile.tileY));
HttpGet getRequest = new HttpGet(url); HttpGet getRequest = new HttpGet(url);
getRequest.addHeader(encodingHeader); getRequest.addHeader(encodingHeader);
mRequest = getRequest;
mMapGenerator = mapDatabaseCallback; mMapGenerator = mapDatabaseCallback;
mCurTagCnt = 0; 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; mScaleFactor = 1 / 100f;
if (tile.zoomLevel < 12) if (tile.zoomLevel < 12)
mScaleFactor = (float) Math.pow(2, (12 - tile.zoomLevel)) / 100f; mScaleFactor = (float) Math.pow(2, (12 - tile.zoomLevel)) / 100f;
@ -101,22 +103,16 @@ public class MapDatabase implements IMapDatabase {
try { try {
HttpResponse response = mClient.execute(getRequest); HttpResponse response = mClient.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode(); final int statusCode = response.getStatusLine().getStatusCode();
final HttpEntity entity = response.getEntity();
if (statusCode != HttpStatus.SC_OK) { if (statusCode != HttpStatus.SC_OK) {
Log.d(TAG, "Http response " + statusCode); 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; InputStream is = null;
GZIPInputStream zis = null; GZIPInputStream zis = null;
try { try {
// is = AndroidHttpClient.getUngzippedContent(entity);
is = entity.getContent(); is = entity.getContent();
zis = new GZIPInputStream(is); zis = new GZIPInputStream(is);
@ -131,12 +127,19 @@ public class MapDatabase implements IMapDatabase {
} }
} catch (SocketException ex) { } catch (SocketException ex) {
Log.d(TAG, "Socket exception: " + ex.getMessage()); Log.d(TAG, "Socket exception: " + ex.getMessage());
return QueryResult.FAILED;
} catch (SocketTimeoutException ex) { } catch (SocketTimeoutException ex) {
Log.d(TAG, "Socket exception: " + ex.getMessage()); Log.d(TAG, "Socket Timeout exception: " + ex.getMessage());
return QueryResult.FAILED;
} catch (Exception ex) { } catch (Exception ex) {
getRequest.abort(); getRequest.abort();
ex.printStackTrace(); ex.printStackTrace();
return QueryResult.FAILED;
} }
mRequest = null;
// Log.d(TAG, "get tile << : " + tile);
return QueryResult.SUCCESS;
} }
@Override @Override
@ -163,7 +166,7 @@ public class MapDatabase implements IMapDatabase {
HttpConnectionParams.setConnectionTimeout(params, 10 * 1000); HttpConnectionParams.setConnectionTimeout(params, 10 * 1000);
HttpConnectionParams.setSoTimeout(params, 60 * 1000); HttpConnectionParams.setSoTimeout(params, 60 * 1000);
HttpConnectionParams.setSocketBufferSize(params, 8192); HttpConnectionParams.setSocketBufferSize(params, 16384);
mClient = new DefaultHttpClient(params); mClient = new DefaultHttpClient(params);
HttpClientParams.setRedirecting(params, false); HttpClientParams.setRedirecting(params, false);
SchemeRegistry schemeRegistry = new SchemeRegistry(); SchemeRegistry schemeRegistry = new SchemeRegistry();
@ -190,7 +193,7 @@ public class MapDatabase implements IMapDatabase {
return null; 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 final byte[] buffer = new byte[BUFFER_SIZE];
private int bufferPos; 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_TAGS = 1;
private static final int TAG_TILE_WAYS = 2; private static final int TAG_TILE_WAYS = 2;
private static final int TAG_TILE_NODES = 3; private static final int TAG_TILE_POLY = 3;
private static final int TAG_WAY_TAGS = 1; private static final int TAG_TILE_NODES = 4;
private static final int TAG_WAY_INDEX = 2; private static final int TAG_WAY_TAGS = 11;
private static final int TAG_WAY_COORDS = 3; private static final int TAG_WAY_INDEX = 12;
private static final int TAG_WAY_LAYER = 4; 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_TAGS = 11;
// private static final int TAG_NODE_COORDS = 2; 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 { private boolean decode(InputStream is) throws IOException {
inputStream = is; inputStream = is;
@ -228,7 +238,11 @@ public class MapDatabase implements IMapDatabase {
break; break;
case TAG_TILE_WAYS: case TAG_TILE_WAYS:
decodeTileWays(); decodeTileWays(false);
break;
case TAG_TILE_POLY:
decodeTileWays(true);
break; break;
case TAG_TILE_NODES: case TAG_TILE_NODES:
@ -248,16 +262,23 @@ public class MapDatabase implements IMapDatabase {
Tag tag = tagHash.get(tagString); Tag tag = tagHash.get(tagString);
if (tag == null) { 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); tagHash.put(tagString, tag);
} }
curTags[mCurTagCnt++] = tag; // FIXME ...
if (mCurTagCnt < 250)
curTags[mCurTagCnt++] = tag;
// Log.d(TAG, "tag:" + tag); //
return true; return true;
} }
private boolean decodeTileWays() throws IOException { private boolean decodeTileWays(boolean polygon) throws IOException {
int bytes = decodeVarint32(); int bytes = decodeVarint32();
int end = bytesRead + bytes; int end = bytesRead + bytes;
@ -265,6 +286,11 @@ public class MapDatabase implements IMapDatabase {
int tagCnt = 0; int tagCnt = 0;
int coordCnt = 0; int coordCnt = 0;
int layer = 0; int layer = 0;
Tag[] tags = null;
short[] index = null;
boolean skip = false;
boolean fail = false;
while (bytesRead < end) { while (bytesRead < end) {
// read tag and wire type // read tag and wire type
@ -275,54 +301,56 @@ public class MapDatabase implements IMapDatabase {
int tag = (val >> 3); int tag = (val >> 3);
// int wireType = val & 7; // int wireType = val & 7;
// Log.d(TAG, "way " + tag + " " + wireType + " bytes:" + bytes); // Log.d(TAG, "way " + tag + " " + wireType + " bytes:" + bytes);
int cnt;
switch (tag) { switch (tag) {
case TAG_WAY_TAGS: case TAG_WAY_TAGS:
tagCnt = decodeWayTags(); tags = decodeWayTags(tagCnt);
break; break;
case TAG_WAY_INDEX: case TAG_WAY_INDEX:
indexCnt = decodeWayIndices(); index = decodeWayIndices(indexCnt);
break; break;
case TAG_WAY_COORDS: case TAG_WAY_COORDS:
coordCnt = decodeWayCoordinates(); cnt = decodeWayCoordinates(skip);
if (cnt != coordCnt) {
Log.d(TAG, "EEEK wrong number of coordintes");
fail = true;
}
break; break;
case TAG_WAY_LAYER: case TAG_WAY_LAYER:
layer = decodeVarint32(); layer = decodeVarint32();
break; 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: default:
Log.d(TAG, "invalid type for way: " + tag); 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; 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; float[] coords = tmpCoords;
int pos = 0; int pos = 0;
if (coordCnt != sum) {
Log.d(TAG, "way length is wrong " + coordCnt + " " + sum);
return false;
}
float z = mScaleFactor; float z = mScaleFactor;
for (int j = 0, m = indexCnt; j < m; j++) { for (int j = 0, m = indexCnt; j < m; j++) {
float lastX = 0; float lastX = 0;
@ -332,23 +360,86 @@ public class MapDatabase implements IMapDatabase {
lastX = coords[pos] = (coords[pos] * z) + lastX; lastX = coords[pos] = (coords[pos] * z) + lastX;
lastY = coords[pos + 1] = (coords[pos + 1] * z) + lastY; 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; return true;
} }
private boolean decodeTileNodes() throws IOException { private boolean decodeTileNodes() throws IOException {
int bytes = decodeVarint32(); 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; 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_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 float[] tmpCoords = new float[MAX_WAY_COORDS];
// private boolean ensureBufferSize(int size) throws IOException { // private boolean ensureBufferSize(int size) throws IOException {
@ -358,47 +449,62 @@ public class MapDatabase implements IMapDatabase {
// return true; // return true;
// } // }
private int decodeWayTags() throws IOException { private Tag[] decodeWayTags(int tagCnt) throws IOException {
int bytes = decodeVarint32(); int bytes = decodeVarint32();
// Log.d(TAG, "way tags: " + bytes);
Tag[] tags = new Tag[tagCnt];
int cnt = 0; int cnt = 0;
int end = bytesRead + bytes; int end = bytesRead + bytes;
int max = curTags.length;
while (bytesRead < end) while (bytesRead < end) {
tmpTags[cnt++] = decodeVarint32(); 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(); int bytes = decodeVarint32();
// Log.d(TAG, "way indices: " + bytes);
short[] index = new short[indexCnt];
int cnt = 0; int cnt = 0;
int end = bytesRead + bytes; int end = bytesRead + bytes;
while (bytesRead < end) { while (bytesRead < end) {
int val = decodeVarint32(); int val = decodeVarint32();
if (cnt >= MAX_WAY_INDICES) { if (cnt < indexCnt)
index[cnt++] = (short) (val * 2);
MAX_WAY_INDICES += 128; // else DEBUG...
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;
} }
return cnt; return index;
} }
private int decodeWayCoordinates() throws IOException { private int decodeWayCoordinates(boolean skip) throws IOException {
int bytes = decodeVarint32(); int bytes = decodeVarint32();
readBuffer(bytes); readBuffer(bytes);
if (skip) {
bufferPos += bytes;
return 0;
}
int pos = bufferPos; int pos = bufferPos;
int end = pos + bytes; int end = pos + bytes;
@ -511,7 +617,18 @@ public class MapDatabase implements IMapDatabase {
buffer[bufferSize - 1] = 0; // FIXME is this needed? buffer[bufferSize - 1] = 0; // FIXME is this needed?
break; break;
} }
bufferSize += len; 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 " // Log.d(TAG, "needed " + size + " pos " + bufferPos + ", size "
@ -614,8 +731,12 @@ public class MapDatabase implements IMapDatabase {
@Override @Override
public void cancel() { public void cancel() {
mCanceled = true; mCanceled = true;
mClient.getConnectionManager().shutdown(); if (mRequest != null) {
mClient = 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.IMapDatabase;
import org.mapsforge.database.IMapDatabaseCallback; import org.mapsforge.database.IMapDatabaseCallback;
import org.mapsforge.database.MapFileInfo; import org.mapsforge.database.MapFileInfo;
import org.mapsforge.database.QueryResult;
import org.postgresql.PGConnection; import org.postgresql.PGConnection;
import android.util.Log;
/** /**
* *
* *
*/ */
public class MapDatabase implements IMapDatabase { public class MapDatabase implements IMapDatabase {
private final static String TAG = "MapDatabase";
private static final String QUERY = "SELECT tags, geom FROM __get_tile(?,?,?)"; private static final String QUERY = "SELECT tags, geom FROM __get_tile(?,?,?)";
private final float mScale = 1; // 1000000.0f; private final float mScale = 1; // 1000000.0f;
@ -47,7 +52,7 @@ public class MapDatabase implements IMapDatabase {
private int mCoordPos = 0; private int mCoordPos = 0;
private int mIndexPos = 0; private int mIndexPos = 0;
private float[] mCoords = new float[100000]; private float[] mCoords = new float[100000];
private int[] mIndex = new int[10000]; private short[] mIndex = new short[10000];
private Tag[] mTags; private Tag[] mTags;
@ -66,7 +71,7 @@ public class MapDatabase implements IMapDatabase {
private boolean connect() { private boolean connect() {
Connection conn = null; 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(); Properties dbOpts = new Properties();
dbOpts.setProperty("user", "osm"); dbOpts.setProperty("user", "osm");
@ -97,44 +102,45 @@ public class MapDatabase implements IMapDatabase {
} }
@Override @Override
public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) { public QueryResult executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
if (connection == null) { if (connection == null) {
if (!connect()) if (!connect())
return; return QueryResult.FAILED;
} }
ResultSet r; ResultSet r;
try { try {
prepQuery.setLong(1, tile.pixelX); prepQuery.setLong(1, tile.tileX * 256);
prepQuery.setLong(2, tile.pixelY); prepQuery.setLong(2, tile.tileY * 256);
prepQuery.setInt(3, tile.zoomLevel); prepQuery.setInt(3, tile.zoomLevel);
System.out.println("" + prepQuery.toString()); Log.d(TAG, "" + prepQuery.toString());
prepQuery.execute(); prepQuery.execute();
r = prepQuery.getResultSet(); r = prepQuery.getResultSet();
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
connection = null; connection = null;
return; return QueryResult.FAILED;
} }
byte[] b = null; byte[] b = null;
PGHStore h = null; PGHStore h = null;
int cnt = 0;
try { try {
while (r != null && r.next()) { while (r != null && r.next()) {
mIndexPos = 0; mIndexPos = 0;
mCoordPos = 0; mCoordPos = 0;
cnt++;
try { try {
Object obj = r.getObject(1); Object obj = r.getObject(1);
h = null; h = null;
if (obj instanceof PGHStore) if (obj instanceof PGHStore)
h = (PGHStore) obj; h = (PGHStore) obj;
else else {
Log.d(TAG, "no tags: skip way");
continue; continue;
}
b = r.getBytes(2); b = r.getBytes(2);
} catch (SQLException e) { } catch (SQLException e) {
@ -142,15 +148,16 @@ public class MapDatabase implements IMapDatabase {
continue; continue;
} }
if (b == null) if (b == null) {
// Log.d(TAG, "no geometry: skip way");
continue; continue;
}
mTags = new Tag[h.size()]; mTags = new Tag[h.size()];
int i = 0; int i = 0;
for (Entry<String, String> t : h.entrySet()) { for (Entry<String, String> t : h.entrySet()) {
if (t.getKey() == null) { if (t.getKey() == null) {
System.out.println("no KEY !!! "); Log.d(TAG, "no KEY !!! ");
break; break;
} }
Tag tag = tagHash.get(t); Tag tag = tagHash.get(t);
@ -164,18 +171,27 @@ public class MapDatabase implements IMapDatabase {
if (i < mTags.length) if (i < mTags.length)
continue; continue;
parse(b); boolean polygon = parse(b);
if (mIndexPos == 0) if (mIndexPos == 0) {
Log.d(TAG, "no index: skip way");
continue; continue;
} else if (mIndexPos == 1) {
mapDatabaseCallback.renderPointOfInterest((byte) 0, mCoords[1],
mCoords[0], mTags);
} else {
int[] idx = new int[mIndexPos]; short[] idx = new short[mIndexPos];
System.arraycopy(mIndex, 0, idx, 0, mIndexPos); System.arraycopy(mIndex, 0, idx, 0, mIndexPos);
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, idx, true); mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, idx, polygon);
}
} }
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
connection = null; connection = null;
return QueryResult.FAILED;
} }
// Log.d(TAG, "rows: " + cnt);
return QueryResult.SUCCESS;
} }
@Override @Override
@ -237,11 +253,11 @@ public class MapDatabase implements IMapDatabase {
* @param value * @param value
* ... * ...
*/ */
private void parse(byte[] value) { private boolean parse(byte[] value) {
parseGeometry(valueGetterForEndian(value)); return parseGeometry(valueGetterForEndian(value));
} }
private void parseGeometry(ValueGetter data) { private boolean parseGeometry(ValueGetter data) {
byte endian = data.getByte(); // skip and test endian flag byte endian = data.getByte(); // skip and test endian flag
if (endian != data.endian) { if (endian != data.endian) {
throw new IllegalArgumentException("Endian inconsistency!"); throw new IllegalArgumentException("Endian inconsistency!");
@ -255,7 +271,7 @@ public class MapDatabase implements IMapDatabase {
boolean haveS = (typeword & 0x20000000) != 0; boolean haveS = (typeword & 0x20000000) != 0;
// int srid = Geometry.UNKNOWN_SRID; // int srid = Geometry.UNKNOWN_SRID;
boolean polygon = false;
if (haveS) { if (haveS) {
// srid = Geometry.parseSRID(data.getInt()); // srid = Geometry.parseSRID(data.getInt());
data.getInt(); data.getInt();
@ -269,6 +285,7 @@ public class MapDatabase implements IMapDatabase {
break; break;
case Geometry.POLYGON: case Geometry.POLYGON:
parsePolygon(data, haveZ, haveM); parsePolygon(data, haveZ, haveM);
polygon = true;
break; break;
case Geometry.MULTIPOINT: case Geometry.MULTIPOINT:
parseMultiPoint(data); parseMultiPoint(data);
@ -278,6 +295,7 @@ public class MapDatabase implements IMapDatabase {
break; break;
case Geometry.MULTIPOLYGON: case Geometry.MULTIPOLYGON:
parseMultiPolygon(data); parseMultiPolygon(data);
polygon = true;
break; break;
case Geometry.GEOMETRYCOLLECTION: case Geometry.GEOMETRYCOLLECTION:
parseCollection(data); parseCollection(data);
@ -288,14 +306,16 @@ public class MapDatabase implements IMapDatabase {
// if (srid != Geometry.UNKNOWN_SRID) { // if (srid != Geometry.UNKNOWN_SRID) {
// result.setSrid(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 X = data.getDouble();
// double Y = data.getDouble(); // double Y = data.getDouble();
data.getDouble(); mCoords[0] = (float) (data.getDouble() * mScale);
data.getDouble(); mCoords[1] = (float) (data.getDouble() * mScale);
mIndex[0] = 2;
mIndexPos = 1;
if (haveZ) if (haveZ)
data.getDouble(); data.getDouble();
@ -341,7 +361,7 @@ public class MapDatabase implements IMapDatabase {
if (haveM) if (haveM)
data.getDouble(); data.getDouble();
} }
mIndex[mIndexPos++] = count * 2; mIndex[mIndexPos++] = (short) (count * 2);
} }
private void parsePolygon(ValueGetter data, boolean haveZ, boolean haveM) { private void parsePolygon(ValueGetter data, boolean haveZ, boolean haveM) {