- making oscimap default backend

- added about-screen
- added TreeTile for Tile lookup, dropping that HashMap
- using simple line-shader instead of std-derivatives one,
  about twice as faster here
- use distance calculation from MapRenderer - removing TileScheduler
- no need for MapGeneratorJob, pass MapTile directly to MapWorkers
- added two-finger tap gestures for zoom-in/out
- added tub/tron rendertheme
- started caching for oscimap
- add x/y coordinates to MapPosition, using it in MapRenderer
- create tag hash when needed
- no need for long tile coordinates max zoomlevel 31 should suffice
This commit is contained in:
Hannes Janetzek 2012-09-03 00:13:13 +02:00
parent 78e39af35a
commit 1a27f56313
61 changed files with 2779 additions and 2076 deletions

View File

@ -29,6 +29,7 @@
</activity>
<activity android:name=".preferences.EditPreferences" />
<activity android:name=".filepicker.FilePicker" />
<activity android:name=".InfoView" android:theme="@android:style/Theme.NoTitleBar" />
</application>
</manifest>

View File

@ -6,9 +6,10 @@
<meta http-equiv="Content-Style-Type" content="text/css" />
</head>
<body style="padding: 0.5em;">
<p style="text-align: center;"><img alt="mapsforge logo" src="file:///android_asset/mapsforge_logo.png" style="width: 255px; height: 223px;" /><br />Version 0.2.4</p>
<p>This software is a part of the <a href="http://mapsforge.org/">mapsforge</a> project and distributed under the <a href="http://www.gnu.org/licenses/lgpl.html">LGPL3 license</a>.</p>
<p>Map data © <a href="http://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>.</p>
<p>Please report all bugs and feature requests either via our <a href="https://code.google.com/p/mapsforge/issues/list">issue tracker</a> or our public <a href="http://groups.google.com/group/mapsforge-dev">mapsforge-dev mailing list</a>.</p>
<p style="text-align: center;"><img alt="mapsforge logo" src="file:///android_asset/globe2.png" style="width: 72px; height: 72px;" /><br />Version 0.2.1</p>
<p> <a href="https://code.google.com/p/vector-tile-map">OpenScienceMap</a> is distributed under the <a href="http://www.gnu.org/licenses/lgpl.html">LGPL3 license</a>.</p>
<p> This software is based on <a href="https://code.google.com/p/mapsforge">mapsforge</a> library 0.2.4.</p>
<p>Map data © <a href="http://www.openstreetmap.org/">OpenStreetMap</a> contributors, still using <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>.</p>
<p>Please report all bugs and feature requests via our <a href="https://code.google.com/p/vector-tile-map/issues/list">issue tracker</a> </p>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

View File

@ -11,17 +11,17 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<ToggleButton
<!-- <ToggleButton
android:id="@+id/snapToLocationView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="10dip"
android:layout_marginTop="10dip"
android:layout_marginBottom="10dip"
android:background="@drawable/snap_to_position"
android:textOff=""
android:textOn=""
android:visibility="gone" />
android:visibility="gone" />-->
</RelativeLayout>

View File

@ -47,6 +47,9 @@
<item
android:id="@+id/menu_render_theme_osmarender"
android:title="@string/menu_render_theme_osmarender"/>
<item
android:id="@+id/menu_render_theme_tronrender"
android:title="@string/menu_render_theme_tronrender"/>
<item
android:id="@+id/menu_render_theme_select_file"
android:title="@string/menu_render_theme_select_file"/>
@ -58,9 +61,9 @@
android:showAsAction="never"
android:title="@string/menu_mapfile"/>
<!-- <item
android:id="@+id/menu_info_map_file"
android:title="@string/menu_info_map_file"/> -->
<item
android:id="@+id/menu_info_about"
android:title="@string/menu_info_about"/>
</menu>
</item>

View File

@ -48,6 +48,9 @@
<!-- <item
android:id="@+id/menu_info_map_file"
android:title="@string/menu_info_map_file"/> -->
<item
android:id="@+id/menu_info_about"
android:title="@string/menu_info_about"/>
</menu>
</item>
@ -61,6 +64,9 @@
<item
android:id="@+id/menu_render_theme_osmarender"
android:title="@string/menu_render_theme_osmarender"/>
<item
android:id="@+id/menu_render_theme_tronrender"
android:title="@string/menu_render_theme_tronrender"/>
<item
android:id="@+id/menu_render_theme_select_file"
android:title="@string/menu_render_theme_select_file"/>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string-array name="preferences_map_generator_values">
<!-- <string-array name="preferences_map_generator_values">
<item>Mapfile</item>
<item>PostGIS</item>
<item>OpenScienceMap</item>
</string-array>
</string-array> -->
<string-array name="preferences_scale_bar_unit_values">
<item>angloamerikanisch</item>

View File

@ -1,11 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string-array name="preferences_map_generator_values">
<item>Mapfile</item>
<item>PostGIS</item>
<item>OpenScienceMap</item>
</string-array>
<string-array name="preferences_text_scale_values">
<item>hyvin pieni</item>
<item>pieni</item>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string-array name="preferences_map_generator_values">
<!-- <string-array name="preferences_map_generator_values">
<item>Mapfile</item>
<item>PostGIS</item>
<item>OpenScienceMap</item>
</string-array>
</string-array> -->
<string-array name="preferences_text_scale_values">
<item>minuscola</item>

View File

@ -1,31 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string-array name="preferences_map_database_keys">
<item>MAP_READER</item>
<item>POSTGIS_READER</item>
<item>PBMAP_READER</item>
</string-array>
<string name="preferences_map_database_default">POSTGIS_READER</string>
<string-array name="preferences_scale_bar_unit_keys">
<item>imperial</item>
<item>metric</item>
</string-array>
<string name="preferences_scale_bar_unit_default">metric</string>
<string-array name="preferences_map_database_keys">
<!-- <item>MAP_READER</item> -->
<item>POSTGIS_READER</item>
<item>PBMAP_READER</item>
</string-array>
<string name="preferences_map_database_default">PBMAP_READER</string>
<string-array name="preferences_scale_bar_unit_keys">
<item>imperial</item>
<item>metric</item>
</string-array>
<string name="preferences_scale_bar_unit_default">metric</string>
<string-array name="preferences_text_scale_keys">
<item>0.7</item>
<item>0.85</item>
<item>1.0</item>
<item>1.3</item>
<item>1.6</item>
</string-array>
<string name="preferences_text_scale_default">1.0</string>
<string-array name="view_sections">
<item>Map</item>
<item>Routes</item>
<item>Overlays</item>
<item>etc</item>
</string-array>
<string-array name="preferences_text_scale_keys">
<item>0.7</item>
<item>0.85</item>
<item>1.0</item>
<item>1.3</item>
<item>1.6</item>
</string-array>
<string name="preferences_text_scale_default">1.0</string>
<string-array name="view_sections">
<item>Map</item>
<item>Routes</item>
<item>Overlays</item>
<item>etc</item>
</string-array>
</resources>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string-array name="preferences_map_generator_values">
<item>Mapfile</item>
<item>PostGIS</item>
<!-- <item>Mapfile</item> -->
<item>PostGIS</item>
<item>OpenScienceMap</item>
</string-array>
@ -59,6 +59,7 @@
<string name="menu_preferences">Preferences</string>
<string name="menu_render_theme">Render theme</string>
<string name="menu_render_theme_osmarender">Default Theme</string>
<string name="menu_render_theme_tronrender">Tube Theme</string>
<string name="menu_render_theme_select_file">Select XML file …</string>
<string name="menu_screenshot">Screenshot</string>
<string name="menu_screenshot_jpeg">JPEG (lossy)</string>

View File

@ -3,7 +3,6 @@
<style name="MyActionBar" parent="android:style/Widget.Holo.Light.ActionBar">
<item name="android:background">@drawable/action_bar</item>
<item name="android:windowActionBarOverlay">true</item>
</style>
<style name="Theme.TileMap" parent="android:style/Theme.Holo">

View File

@ -15,7 +15,7 @@
package org.mapsforge.android;
import org.mapsforge.android.mapgenerator.IMapGenerator;
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.mapgenerator.MapTile;
import org.mapsforge.android.rendertheme.RenderTheme;
import android.opengl.GLSurfaceView;
@ -26,11 +26,11 @@ import android.opengl.GLSurfaceView;
public interface IMapRenderer extends GLSurfaceView.Renderer {
/**
* @param mapGeneratorJob
* @param tile
* the mapGeneratorJob holding Tile data
* @return true if the tile was processed
*/
public boolean passTile(MapGeneratorJob mapGeneratorJob);
public boolean passTile(MapTile tile);
/**
* @return true when tile passed to renderer is processed false otherwise. used to lock overwriting resources passed

View File

@ -96,7 +96,7 @@ public abstract class MapActivity extends Activity {
// save the map position and zoom level
MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
if (mapPosition != null) {
GeoPoint geoPoint = mapPosition.geoPoint;
GeoPoint geoPoint = new GeoPoint(mapPosition.lat, mapPosition.lon);
editor.putInt(KEY_LATITUDE, geoPoint.latitudeE6);
editor.putInt(KEY_LONGITUDE, geoPoint.longitudeE6);
editor.putInt(KEY_ZOOM_LEVEL, mapPosition.zoomLevel);

View File

@ -65,9 +65,12 @@ public class MapScaleBar {
private static final int ONE_MILE = 5280;
private static final Paint SCALE_BAR = new Paint(Paint.ANTI_ALIAS_FLAG);
private static final Paint SCALE_BAR_STROKE = new Paint(Paint.ANTI_ALIAS_FLAG);
private static final int[] SCALE_BAR_VALUES_IMPERIAL = { 26400000, 10560000, 5280000, 2640000, 1056000, 528000,
264000, 105600, 52800, 26400, 10560, 5280, 2000, 1000, 500, 200, 100, 50, 20, 10, 5, 2, 1 };
private static final int[] SCALE_BAR_VALUES_METRIC = { 10000000, 5000000, 2000000, 1000000, 500000, 200000, 100000,
private static final int[] SCALE_BAR_VALUES_IMPERIAL = { 26400000, 10560000, 5280000,
2640000, 1056000, 528000,
264000, 105600, 52800, 26400, 10560, 5280, 2000, 1000, 500, 200, 100, 50, 20,
10, 5, 2, 1 };
private static final int[] SCALE_BAR_VALUES_METRIC = { 10000000, 5000000, 2000000,
1000000, 500000, 200000, 100000,
50000, 20000, 10000, 5000, 2000, 1000, 500, 200, 100, 50, 20, 10, 5, 2, 1 };
private static final Paint SCALE_TEXT = new Paint(Paint.ANTI_ALIAS_FLAG);
private static final Paint SCALE_TEXT_STROKE = new Paint(Paint.ANTI_ALIAS_FLAG);
@ -101,7 +104,8 @@ public class MapScaleBar {
MapScaleBar(MapView mapView) {
mMapView = mapView;
mMapScaleBitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Bitmap.Config.ARGB_4444);
mMapScaleBitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT,
Bitmap.Config.ARGB_4444);
mMapScaleCanvas = new Canvas(mMapScaleBitmap);
mTextFields = new HashMap<TextField, String>();
setDefaultTexts();
@ -173,8 +177,8 @@ public class MapScaleBar {
return true;
}
double latitudeDiff = Math.abs(currentMapPosition.geoPoint.getLatitude()
- mMapPosition.geoPoint.getLatitude());
double latitudeDiff = Math.abs(currentMapPosition.lat
- mMapPosition.lat);
if (latitudeDiff > LATITUDE_REDRAW_THRESHOLD) {
return true;
}
@ -245,7 +249,8 @@ public class MapScaleBar {
}
mMapPosition = mMapView.getMapPosition().getMapPosition();
double groundResolution = MercatorProjection.calculateGroundResolution(mMapPosition.geoPoint.getLatitude(),
double groundResolution = MercatorProjection.calculateGroundResolution(
mMapPosition.lat,
mMapPosition.zoomLevel);
int[] scaleBarValues;

View File

@ -24,13 +24,12 @@ import javax.xml.parsers.ParserConfigurationException;
import org.mapsforge.android.input.TouchHandler;
import org.mapsforge.android.mapgenerator.IMapGenerator;
import org.mapsforge.android.mapgenerator.JobParameters;
import org.mapsforge.android.mapgenerator.JobQueue;
import org.mapsforge.android.mapgenerator.MapDatabaseFactory;
import org.mapsforge.android.mapgenerator.MapDatabases;
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.mapgenerator.MapRendererFactory;
import org.mapsforge.android.mapgenerator.MapRenderers;
import org.mapsforge.android.mapgenerator.MapTile;
import org.mapsforge.android.mapgenerator.MapWorker;
import org.mapsforge.android.mapgenerator.Theme;
import org.mapsforge.android.rendertheme.ExternalRenderTheme;
@ -80,9 +79,6 @@ public class MapView extends GLSurfaceView {
private static final Byte DEFAULT_START_ZOOM_LEVEL = Byte.valueOf((byte) 16);
private final MapController mMapController;
// private final MapMover mMapMover;
// private final ZoomAnimator mZoomAnimator;
// private final MapScaleBar mMapScaleBar;
private final MapViewPosition mMapViewPosition;
private final MapZoomControls mMapZoomControls;
@ -95,10 +91,11 @@ public class MapView extends GLSurfaceView {
private JobQueue mJobQueue;
private MapWorker mMapWorkers[];
private int mNumMapWorkers = 4;
private JobParameters mJobParameters;
public DebugSettings debugSettings;
private DebugSettings debugSettings;
private String mMapFile;
private File cacheDir;
/**
* @param context
* the enclosing MapActivity instance.
@ -139,30 +136,25 @@ public class MapView extends GLSurfaceView {
// TODO make this dpi dependent
Tile.TILE_SIZE = 400;
// setWillNotDraw(true);
// setWillNotCacheDrawing(true);
MapActivity mapActivity = (MapActivity) context;
cacheDir = context.getFilesDir();
debugSettings = new DebugSettings(false, false, false, false);
mJobParameters = new JobParameters(DEFAULT_RENDER_THEME, DEFAULT_TEXT_SCALE);
mMapController = new MapController(this);
mMapDatabaseType = mapDatabaseType;
mMapViewPosition = new MapViewPosition(this);
// mMapScaleBar = new MapScaleBar(this);
mMapZoomControls = new MapZoomControls(mapActivity, this);
mProjection = new MapViewProjection(this);
mTouchEventHandler = new TouchHandler(mapActivity, this);
mJobQueue = new JobQueue(this);
// mMapMover = new MapMover(this);
// mMapMover.start();
// mZoomAnimator = new ZoomAnimator(this);
// mZoomAnimator.start();
mJobQueue = new JobQueue();
mMapRenderer = MapRendererFactory.createMapRenderer(this, mapGeneratorType);
mMapWorkers = new MapWorker[mNumMapWorkers];
@ -172,7 +164,6 @@ public class MapView extends GLSurfaceView {
if (mDebugDatabase) {
mapDatabase = MapDatabaseFactory
.createMapDatabase(MapDatabases.JSON_READER);
} else {
mapDatabase = MapDatabaseFactory.createMapDatabase(mapDatabaseType);
}
@ -180,16 +171,18 @@ public class MapView extends GLSurfaceView {
IMapGenerator mapGenerator = mMapRenderer.createMapGenerator();
mapGenerator.setMapDatabase(mapDatabase);
if (i == 0) {
if (i == 0)
mMapDatabase = mapDatabase;
initMapStartPosition();
}
mMapWorkers[i] = new MapWorker(i, this, mapGenerator, mMapRenderer);
mMapWorkers[i].start();
}
if (!setRenderTheme(InternalRenderTheme.OSMARENDER)) {
Log.d(TAG, "EEEK could parse theme");
setMapFile("default");
initMapStartPosition();
if (!setRenderTheme(DEFAULT_RENDER_THEME)) {
Log.d(TAG, "X could not parse theme");
// FIXME show init error dialog
}
@ -197,11 +190,15 @@ public class MapView extends GLSurfaceView {
setEGLContextClientVersion(2);
setRenderer(mMapRenderer);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
if (!debugFrameTime)
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
mapActivity.registerMapView(this);
}
public final static boolean debugFrameTime = false;
private void initMapStartPosition() {
GeoPoint startPoint = getStartPoint();
if (startPoint != null) {
@ -212,7 +209,6 @@ public class MapView extends GLSurfaceView {
if (startZoomLevel != null) {
mMapViewPosition.setZoomLevel(startZoomLevel.byteValue());
}
}
/**
@ -250,13 +246,6 @@ public class MapView extends GLSurfaceView {
return mMapFile;
}
// /**
// * @return the MapMover which is used by this MapView.
// */
// public MapMover getMapMover() {
// return mMapMover;
// }
/**
* @return the current position and zoom level of this MapView.
*/
@ -264,20 +253,6 @@ public class MapView extends GLSurfaceView {
return mMapViewPosition;
}
// /**
// * @return the scale bar which is used in this MapView.
// */
// public MapScaleBar getMapScaleBar() {
// return mMapScaleBar;
// }
// /**
// * @return the zoom controls instance which is used in this MapView.
// */
// public MapZoomControls getMapZoomControls() {
// return mMapZoomControls;
// }
/**
* @return the currently used projection of the map. Do not keep this object for a longer time.
*/
@ -285,33 +260,11 @@ public class MapView extends GLSurfaceView {
return mProjection;
}
// /**
// * @return true if the ZoomAnimator is currently running, false otherwise.
// */
// public boolean isZoomAnimatorRunning() {
// return mZoomAnimator.isExecuting();
// }
// @Override
// public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {
// return mMapMover.onKeyDown(keyCode, keyEvent);
// }
//
// @Override
// public boolean onKeyUp(int keyCode, KeyEvent keyEvent) {
// return mMapMover.onKeyUp(keyCode, keyEvent);
// }
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
return mTouchEventHandler.handleMotionEvent(motionEvent);
}
// @Override
// public boolean onTrackballEvent(MotionEvent motionEvent) {
// return mMapMover.onTrackballEvent(motionEvent);
// }
/**
* Calculates all necessary tiles and adds jobs accordingly.
*/
@ -372,21 +325,13 @@ public class MapView extends GLSurfaceView {
public boolean setMapFile(String mapFile) {
FileOpenResult fileOpenResult = null;
Log.d(TAG, "set mapfile " + mapFile);
Log.i(TAG, "set mapfile " + mapFile);
if (mapFile != null && mapFile.equals(mMapFile)) {
// same map file as before
return false;
}
// mZoomAnimator.pause();
// mMapMover.pause();
// mZoomAnimator.awaitPausing();
// mMapMover.awaitPausing();
// mZoomAnimator.proceed();
// mMapMover.stopMove();
// mMapMover.proceed();
boolean initialized = false;
mJobQueue.clear();
@ -403,7 +348,7 @@ public class MapView extends GLSurfaceView {
if (mapFile != null)
fileOpenResult = mapDatabase.openFile(new File(mapFile));
else
fileOpenResult = mapDatabase.openFile(null);
fileOpenResult = mapDatabase.openFile(cacheDir);
if (fileOpenResult != null && fileOpenResult.isSuccess()) {
mMapFile = mapFile;
@ -417,12 +362,12 @@ public class MapView extends GLSurfaceView {
if (initialized) {
clearAndRedrawMapView();
Log.d(TAG, "mapfile set");
Log.i(TAG, "mapfile set");
return true;
}
mMapFile = null;
Log.d(TAG, "loading mapfile failed");
Log.i(TAG, "loading mapfile failed");
return false;
}
@ -430,6 +375,7 @@ public class MapView extends GLSurfaceView {
private GeoPoint getStartPoint() {
if (mMapDatabase != null && mMapDatabase.hasOpenFile()) {
MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo();
if (mapFileInfo.startPosition != null) {
return mapFileInfo.startPosition;
} else if (mapFileInfo.mapCenter != null) {
@ -443,6 +389,7 @@ public class MapView extends GLSurfaceView {
private Byte getStartZoomLevel() {
if (mMapDatabase != null && mMapDatabase.hasOpenFile()) {
MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo();
if (mapFileInfo.startZoomLevel != null) {
return mapFileInfo.startZoomLevel;
}
@ -464,7 +411,7 @@ public class MapView extends GLSurfaceView {
IMapGenerator mapGenerator;
Log.d(TAG, "setMapDatabase " + mapDatabaseType.name());
Log.i(TAG, "setMapDatabase " + mapDatabaseType.name());
if (mMapDatabaseType == mapDatabaseType)
return;
@ -487,8 +434,6 @@ public class MapView extends GLSurfaceView {
setMapFile(mapFile);
mapWorkersProceed();
Log.d(TAG, ">>>");
}
/**
@ -568,10 +513,10 @@ public class MapView extends GLSurfaceView {
* @param textScale
* the new text scale for the map rendering.
*/
public void setTextScale(float textScale) {
mJobParameters = new JobParameters(mJobParameters.theme, textScale);
clearAndRedrawMapView();
}
// public void setTextScale(float textScale) {
// mJobParameters = new JobParameters(mJobParameters.theme, textScale);
// clearAndRedrawMapView();
// }
/**
* Zooms in or out by the given amount of zoom levels.
@ -603,32 +548,10 @@ public class MapView extends GLSurfaceView {
return true;
}
// @Override
// protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
// super.onLayout(changed, left, top, right, bottom);
// // mMapZoomControls.onLayout(changed, left, top, right, bottom);
// }
// @Override
// protected final void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// // find out how big the zoom controls should be
// mMapZoomControls.measure(
// MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec),
// MeasureSpec.AT_MOST),
// MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
// MeasureSpec.AT_MOST));
//
// // make sure that MapView is big enough to display the zoom controls
// setMeasuredDimension(
// Math.max(MeasureSpec.getSize(widthMeasureSpec),
// mMapZoomControls.getMeasuredWidth()),
// Math.max(MeasureSpec.getSize(heightMeasureSpec),
// mMapZoomControls.getMeasuredHeight()));
// }
@Override
protected synchronized void onSizeChanged(int width, int height, int oldWidth,
int oldHeight) {
mJobQueue.clear();
mapWorkersPause(true);
@ -639,9 +562,6 @@ public class MapView extends GLSurfaceView {
}
void destroy() {
// mMapMover.interrupt();
// mZoomAnimator.interrupt();
for (MapWorker mapWorker : mMapWorkers) {
mapWorker.pause();
mapWorker.interrupt();
@ -655,9 +575,6 @@ public class MapView extends GLSurfaceView {
IMapDatabase mapDatabase = mapWorker.getMapGenerator().getMapDatabase();
mapDatabase.closeFile();
}
// mMapScaleBar.destroy();
}
/**
@ -693,18 +610,12 @@ public class MapView extends GLSurfaceView {
public void onPause() {
super.onPause();
mapWorkersPause(false);
// mMapMover.pause();
// mZoomAnimator.pause();
}
@Override
public void onResume() {
super.onResume();
mapWorkersProceed();
// mMapMover.proceed();
// mZoomAnimator.proceed();
}
/**
@ -715,34 +626,7 @@ public class MapView extends GLSurfaceView {
*/
void setCenterAndZoom(MapPosition mapPosition) {
// if (hasValidCenter()) {
// // calculate the distance between previous and current position
// MapPosition mapPositionOld = mapViewPosition.getMapPosition();
// GeoPoint geoPointOld = mapPositionOld.geoPoint;
// GeoPoint geoPointNew = mapPosition.geoPoint;
// double oldPixelX =
// MercatorProjection.longitudeToPixelX(geoPointOld.getLongitude(),
// mapPositionOld.zoomLevel);
// double newPixelX =
// MercatorProjection.longitudeToPixelX(geoPointNew.getLongitude(),
// mapPosition.zoomLevel);
//
// double oldPixelY =
// MercatorProjection.latitudeToPixelY(geoPointOld.getLatitude(),
// mapPositionOld.zoomLevel);
// double newPixelY =
// MercatorProjection.latitudeToPixelY(geoPointNew.getLatitude(),
// mapPosition.zoomLevel);
// float matrixTranslateX = (float) (oldPixelX - newPixelX);
// float matrixTranslateY = (float) (oldPixelY - newPixelY);
// frameBuffer.matrixPostTranslate(matrixTranslateX,
// matrixTranslateY);
// }
//
mMapViewPosition.setMapCenterAndZoomLevel(mapPosition);
// mapZoomControls.onZoomLevelChange(mapViewPosition.getZoomLevel());
redrawTiles();
}
@ -753,20 +637,17 @@ public class MapView extends GLSurfaceView {
return mMapViewPosition;
}
/**
* @return current JobParameters
*/
public JobParameters getJobParameters() {
return mJobParameters;
}
/**
* add jobs and remember MapWorkers that stuff needs to be done
*
* @param jobs
* tile jobs
*/
public void addJobs(ArrayList<MapGeneratorJob> jobs) {
public void addJobs(ArrayList<MapTile> jobs) {
if (jobs == null) {
mJobQueue.clear();
return;
}
mJobQueue.setJobs(jobs);
for (int i = 0; i < mNumMapWorkers; i++) {
@ -795,4 +676,17 @@ public class MapView extends GLSurfaceView {
mapWorker.proceed();
}
// public final int
// public Handler messageHandler = new Handler() {
//
// @Override
// public void handleMessage(Message msg) {
// switch (msg.what) {
// // handle update
// // .....
// }
// }
//
// };
}

View File

@ -19,6 +19,7 @@ import org.mapsforge.core.MapPosition;
import org.mapsforge.core.MercatorProjection;
import android.util.FloatMath;
import android.util.Log;
/**
* A MapPosition stores the latitude and longitude coordinate of a MapView together with its zoom level.
@ -33,8 +34,7 @@ public class MapViewPosition {
private final MapView mMapView;
private byte mZoomLevel;
private float mScale;
// private float mRotation;
private float mRotation;
MapViewPosition(MapView mapView) {
mMapView = mapView;
@ -43,7 +43,7 @@ public class MapViewPosition {
mLongitude = Double.NaN;
mZoomLevel = -1;
mScale = 1;
// mRotation = 0.0f;
mRotation = 0.0f;
}
/**
@ -61,8 +61,7 @@ public class MapViewPosition {
if (!isValid()) {
return null;
}
GeoPoint geoPoint = new GeoPoint(mLatitude, mLongitude);
return new MapPosition(geoPoint, mZoomLevel, mScale);
return new MapPosition(mLatitude, mLongitude, mZoomLevel, mScale, mRotation);
}
/**
@ -105,28 +104,50 @@ public class MapViewPosition {
/**
* Moves this MapViewPosition by the given amount of pixels.
*
* @param moveHorizontal
* @param mx
* the amount of pixels to move the map horizontally.
* @param moveVertical
* @param my
* the amount of pixels to move the map vertically.
*/
public synchronized void moveMap(float moveHorizontal, float moveVertical) {
public synchronized void moveMap(float mx, float my) {
double pixelX = MercatorProjection.longitudeToPixelX(mLongitude, mZoomLevel);
double pixelY = MercatorProjection.latitudeToPixelY(mLatitude, mZoomLevel);
mLatitude = MercatorProjection.pixelYToLatitude(pixelY - moveVertical / mScale,
mZoomLevel);
// float rad = (float) Math.toRadians(mRotation);
// mx /= mScale;
// my /= mScale;
//
// double x = mx * FloatMath.cos(rad) + my * -FloatMath.sin(rad);
// double y = mx * FloatMath.sin(rad) + my * FloatMath.cos(rad);
//
// double dx = pixelX - x;
// double dy = pixelY - y;
double dx = pixelX - mx / mScale;
double dy = pixelY - my / mScale;
mLatitude = MercatorProjection.pixelYToLatitude(dy, mZoomLevel);
mLatitude = MercatorProjection.limitLatitude(mLatitude);
mLongitude = MercatorProjection.pixelXToLongitude(pixelX - moveHorizontal
/ mScale,
mZoomLevel);
mLongitude = MercatorProjection.limitLongitude(mLongitude);
mLongitude = MercatorProjection.pixelXToLongitude(dx, mZoomLevel);
//
// mLatitude = MercatorProjection.pixelYToLatitude(pixelY - moveVertical / mScale,
// mZoomLevel);
// mLatitude = MercatorProjection.limitLatitude(mLatitude);
//
// mLongitude = MercatorProjection.pixelXToLongitude(pixelX - moveHorizontal
// / mScale, mZoomLevel);
mLongitude = MercatorProjection.wrapLongitude(mLongitude);
// mLongitude = MercatorProjection.limitLongitude(mLongitude);
}
// public synchronized void rotateMap(float angle) {
// mRotation = angle;
// }
public synchronized void rotateMap(float angle) {
mRotation -= angle;
Log.d("...", "angle:" + mRotation);
// mRotation %= 360;
}
synchronized void setMapCenter(GeoPoint geoPoint) {
mLatitude = MercatorProjection.limitLatitude(geoPoint.getLatitude());
@ -134,9 +155,8 @@ public class MapViewPosition {
}
synchronized void setMapCenterAndZoomLevel(MapPosition mapPosition) {
GeoPoint geoPoint = mapPosition.geoPoint;
mLatitude = MercatorProjection.limitLatitude(geoPoint.getLatitude());
mLongitude = MercatorProjection.limitLongitude(geoPoint.getLongitude());
mLatitude = MercatorProjection.limitLatitude(mapPosition.lat);
mLongitude = MercatorProjection.limitLongitude(mapPosition.lon);
mZoomLevel = mMapView.limitZoomLevel(mapPosition.zoomLevel);
}
@ -157,8 +177,9 @@ public class MapViewPosition {
* ...
*/
public synchronized void scaleMap(float scale, float pivotX, float pivotY) {
moveMap(pivotX * (1.0f - scale),
pivotY * (1.0f - scale));
if (pivotY != 0 || pivotY != 0)
moveMap(pivotX * (1.0f - scale),
pivotY * (1.0f - scale));
float s = mScale * scale;

View File

@ -38,14 +38,14 @@ class MapViewProjection implements Projection {
MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
// calculate the pixel coordinates of the top left corner
GeoPoint geoPoint = mapPosition.geoPoint;
double pixelX = MercatorProjection.longitudeToPixelX(geoPoint.getLongitude(), mapPosition.zoomLevel);
double pixelY = MercatorProjection.latitudeToPixelY(geoPoint.getLatitude(), mapPosition.zoomLevel);
double pixelX = MercatorProjection.longitudeToPixelX(mapPosition);
double pixelY = MercatorProjection.latitudeToPixelY(mapPosition);
pixelX -= mMapView.getWidth() >> 1;
pixelY -= mMapView.getHeight() >> 1;
// convert the pixel coordinates to a GeoPoint and return it
return new GeoPoint(MercatorProjection.pixelYToLatitude(pixelY + y, mapPosition.zoomLevel),
return new GeoPoint(MercatorProjection.pixelYToLatitude(pixelY + y,
mapPosition.zoomLevel),
MercatorProjection.pixelXToLongitude(pixelX + x, mapPosition.zoomLevel));
}
@ -72,7 +72,8 @@ class MapViewProjection implements Projection {
@Override
public float metersToPixels(float meters, byte zoom) {
double latitude = mMapView.getMapPosition().getMapCenter().getLatitude();
double groundResolution = MercatorProjection.calculateGroundResolution(latitude, zoom);
double groundResolution = MercatorProjection.calculateGroundResolution(latitude,
zoom);
return (float) (meters * (1 / groundResolution));
}
@ -85,22 +86,25 @@ class MapViewProjection implements Projection {
MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
// calculate the pixel coordinates of the top left corner
GeoPoint geoPoint = mapPosition.geoPoint;
double pixelX = MercatorProjection.longitudeToPixelX(geoPoint.getLongitude(), mapPosition.zoomLevel);
double pixelY = MercatorProjection.latitudeToPixelY(geoPoint.getLatitude(), mapPosition.zoomLevel);
double pixelX = MercatorProjection.longitudeToPixelX(mapPosition);
double pixelY = MercatorProjection.latitudeToPixelY(mapPosition);
pixelX -= mMapView.getWidth() >> 1;
pixelY -= mMapView.getHeight() >> 1;
if (out == null) {
// create a new point and return it
return new Point(
(int) (MercatorProjection.longitudeToPixelX(in.getLongitude(), mapPosition.zoomLevel) - pixelX),
(int) (MercatorProjection.latitudeToPixelY(in.getLatitude(), mapPosition.zoomLevel) - pixelY));
(int) (MercatorProjection.longitudeToPixelX(in.getLongitude(),
mapPosition.zoomLevel) - pixelX),
(int) (MercatorProjection.latitudeToPixelY(in.getLatitude(),
mapPosition.zoomLevel) - pixelY));
}
// reuse the existing point
out.x = (int) (MercatorProjection.longitudeToPixelX(in.getLongitude(), mapPosition.zoomLevel) - pixelX);
out.y = (int) (MercatorProjection.latitudeToPixelY(in.getLatitude(), mapPosition.zoomLevel) - pixelY);
out.x = (int) (MercatorProjection.longitudeToPixelX(in.getLongitude(),
mapPosition.zoomLevel) - pixelX);
out.y = (int) (MercatorProjection.latitudeToPixelY(in.getLatitude(),
mapPosition.zoomLevel) - pixelY);
return out;
}
@ -108,7 +112,8 @@ class MapViewProjection implements Projection {
public Point toPoint(GeoPoint in, Point out, byte zoom) {
if (out == null) {
// create a new point and return it
return new Point((int) MercatorProjection.longitudeToPixelX(in.getLongitude(), zoom),
return new Point((int) MercatorProjection.longitudeToPixelX(
in.getLongitude(), zoom),
(int) MercatorProjection.latitudeToPixelY(in.getLatitude(), zoom));
}

View File

@ -72,7 +72,8 @@ public class MapZoomControls {
/**
* Default {@link Gravity} of the zoom controls.
*/
private static final int DEFAULT_ZOOM_CONTROLS_GRAVITY = Gravity.BOTTOM | Gravity.RIGHT;
private static final int DEFAULT_ZOOM_CONTROLS_GRAVITY = Gravity.BOTTOM
| Gravity.RIGHT;
/**
* Default maximum zoom level.
@ -97,7 +98,8 @@ public class MapZoomControls {
/**
* Delay in milliseconds after which the zoom controls disappear.
*/
private static final long ZOOM_CONTROLS_TIMEOUT = ViewConfiguration.getZoomControlsTimeout();
private static final long ZOOM_CONTROLS_TIMEOUT = ViewConfiguration
.getZoomControlsTimeout();
private boolean mGravityChanged;
private boolean mShowMapZoomControls;
@ -220,7 +222,8 @@ public class MapZoomControls {
return (right - left - zoomControlsWidth) / 2;
case Gravity.RIGHT:
return right - left - zoomControlsWidth - ZOOM_CONTROLS_HORIZONTAL_PADDING;
return right - left - zoomControlsWidth
- ZOOM_CONTROLS_HORIZONTAL_PADDING;
}
throw new IllegalArgumentException("unknown horizontal gravity: " + gravity);
@ -251,7 +254,8 @@ public class MapZoomControls {
private void showZoomControlsWithTimeout() {
showZoomControls();
mZoomControlsHideHandler.sendEmptyMessageDelayed(MSG_ZOOM_CONTROLS_HIDE, ZOOM_CONTROLS_TIMEOUT);
mZoomControlsHideHandler.sendEmptyMessageDelayed(MSG_ZOOM_CONTROLS_HIDE,
ZOOM_CONTROLS_TIMEOUT);
}
int getMeasuredHeight() {

View File

@ -15,38 +15,33 @@
package org.mapsforge.android.glrenderer;
import org.mapsforge.android.mapgenerator.MapTile;
import org.mapsforge.core.Tile;
class GLMapTile extends MapTile {
long lastDraw = 0;
// VBO layout:
// 16 bytes fill coordinates
// n bytes polygon vertices
// m bytes lines vertices
VertexBufferObject vbo;
// polygonOffset is always 8
// polygonOffset in vbo is always 16 bytes,
int lineOffset;
TextTexture texture;
// Tile data set by MapGenerator:
LineLayer lineLayers;
PolygonLayer polygonLayers;
TextItem labels;
boolean newData;
boolean loading;
// pixel coordinates (y-flipped)
final long x;
final long y;
// pointer in TileTree
TreeTile rel;
final GLMapTile[] child = { null, null, null, null };
GLMapTile parent;
GLMapTile(long tileX, long tileY, byte zoomLevel) {
GLMapTile(int tileX, int tileY, byte zoomLevel) {
super(tileX, tileY, zoomLevel);
x = pixelX;
y = pixelY + Tile.TILE_SIZE;
}
}

View File

@ -67,6 +67,8 @@ class LineLayers {
return true;
}
static final boolean mFast = true;
static LineLayer drawLines(GLMapTile tile, LineLayer layer, int next, float[] matrix,
float div, double zoom, float scale) {
@ -88,18 +90,17 @@ class LineLayers {
glUniformMatrix4fv(hLineMatrix, 1, false, matrix, 0);
// if (diff != 0)
// // diff < 0 means tile is parent
// z = (diff > 0) ? 1.0f / (1 << diff) : (1 << -diff);
// scale factor to map one pixel on tile to one pixel on screen:
// float pixel = 2.0f / (scale * z);
// GLES20.glUniform1f(hLineScale, pixel);
float pixel = 2.0f / (scale * z);
if (mFast)
GLES20.glUniform1f(hLineScale, pixel);
else
GLES20.glUniform1f(hLineScale, 0);
// line scale factor (for non fixed lines)
float s = FloatMath.sqrt(scale * z);
boolean blur = false;
GLES20.glUniform1f(hLineScale, 0);
LineLayer l = layer;
for (; l != null && l.layer < next; l = l.next) {
@ -120,11 +121,16 @@ class LineLayers {
}
if (blur) {
GLES20.glUniform1f(hLineScale, 0);
if (mFast)
GLES20.glUniform1f(hLineScale, pixel);
else
GLES20.glUniform1f(hLineScale, 0);
blur = false;
}
if (l.isOutline) {
for (LineLayer o = l.outlines; o != null; o = o.outlines) {
if (line.blur != 0) {
GLES20.glUniform1f(hLineScale, (l.width + o.width) / (scale * z)
- (line.blur / (scale * z)));

View File

@ -14,8 +14,10 @@
*/
package org.mapsforge.android.glrenderer;
import org.mapsforge.android.DebugSettings;
import org.mapsforge.android.MapView;
import org.mapsforge.android.mapgenerator.IMapGenerator;
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.mapgenerator.MapTile;
import org.mapsforge.android.rendertheme.IRenderCallback;
import org.mapsforge.android.rendertheme.RenderTheme;
import org.mapsforge.android.rendertheme.renderinstruction.Area;
@ -81,12 +83,24 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
private RenderInstruction[] mRenderInstructions = null;
private final String TAG_WATER = "water".intern();
private final MapView mMapView;
private final Tag[] debugTagBox = { new Tag("debug", "box") };
private final Tag[] debugTagWay = { new Tag("debug", "way") };
private final Tag[] debugTagArea = { new Tag("debug", "area") };
private final float[] debugBoxCoords = { 0, 0, 0, Tile.TILE_SIZE,
Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE, 0, 0, 0 };
private final short[] debugBoxIndex = { 10 };
private float mProjectionScaleFactor;
/**
*
* @param mapView
* the MapView
*/
public MapGenerator() {
public MapGenerator(MapView mapView) {
Log.d(TAG, "init DatabaseRenderer");
mMapView = mapView;
}
private float mPoiX = 256;
@ -115,8 +129,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
if (mMapProjection != null)
{
long x = mCurrentTile.x;
long y = mCurrentTile.y;
long x = mCurrentTile.pixelX;
long y = mCurrentTile.pixelY + Tile.TILE_SIZE;
long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel;
double divx, divy;
@ -163,6 +177,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mTagName = null;
mProjected = false;
mCurLineLayer = null;
mDrawingLayer = getValidLayer(layer) * mLevels;
mSimplify = 0.5f;
@ -325,9 +340,10 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
}
}
if (lineLayer == null)
if (lineLayer == null) {
mCurLineLayer = null;
return;
}
if (line.outline) {
lineLayer.addOutline(mCurLineLayer);
return;
@ -355,45 +371,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
}
pos += length;
}
// if (line.outline < 0)
// return;
//
// Line outline = MapGenerator.renderTheme.getOutline(line.outline);
//
// if (outline == null)
// return;
//
// numLayer = mDrawingLayer + outline.getLevel();
//
// l = mLineLayers;
//
// if (l == null || l.layer > numLayer) {
// // insert new layer at start
// outlineLayer = new LineLayer(numLayer, outline, w, true);
// // outlineLayer = LineLayers.get(numLayer, outline, w, true);
// outlineLayer.next = l;
// mLineLayers = outlineLayer;
// } else {
// while (l != null) {
// if (l.layer == numLayer) {
// outlineLayer = l;
// break;
// }
// // insert new layer between current and next layer
// if (l.next == null || l.next.layer > numLayer) {
// outlineLayer = new LineLayer(numLayer, outline, w, true);
// // outlineLayer = LineLayers.get(numLayer, outline, w, true);
// outlineLayer.next = l.next;
// l.next = outlineLayer;
// }
// l = l.next;
// }
// }
//
// if (outlineLayer != null)
// outlineLayer.addOutline(lineLayer);
}
@Override
@ -469,20 +446,27 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
boolean mDebugDrawUnmatched;
@Override
public boolean executeJob(MapGeneratorJob mapGeneratorJob) {
public boolean executeJob(MapTile mapTile) {
GLMapTile tile;
if (mMapDatabase == null)
return false;
tile = mCurrentTile = (GLMapTile) mapGeneratorJob.tile;
mDebugDrawPolygons = !mapGeneratorJob.debugSettings.mDisablePolygons;
mDebugDrawUnmatched = mapGeneratorJob.debugSettings.mDrawUnmatchted;
tile = mCurrentTile = (GLMapTile) mapTile;
DebugSettings debugSettings = mMapView.getDebugSettings();
if (tile.isLoading || tile.isReady || tile.isCanceled)
mDebugDrawPolygons = !debugSettings.mDisablePolygons;
mDebugDrawUnmatched = debugSettings.mDrawUnmatchted;
// fixed now....
if (tile.newData || tile.isReady || tile.isCanceled) {
Log.d(TAG, "XXX tile already loaded "
+ tile + " "
+ tile.newData + " "
+ tile.isReady + " "
+ tile.isCanceled);
return false;
tile.isLoading = true;
}
mLevels = MapGenerator.renderTheme.getLevels();
@ -492,10 +476,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
else
setScaleStrokeWidth(STROKE_MAX_ZOOM_LEVEL);
mLineLayers = null;
mPolyLayers = null;
mLabels = null;
// firstMatch = true;
countLines = 0;
countNodes = 0;
@ -516,12 +496,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
return false;
}
if (mapGeneratorJob.debugSettings.mDrawTileFrames) {
final float[] debugBoxCoords = { 0, 0, 0, Tile.TILE_SIZE,
Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE, 0, 0, 0 };
final short[] debugBoxIndex = { 10 };
if (debugSettings.mDrawTileFrames) {
mTagName = new Tag("name", countLines + " " + countNodes + " "
+ tile.toString(), false);
mPoiX = Tile.TILE_SIZE >> 1;
@ -533,21 +508,20 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mDrawingLayer = 10 * mLevels;
MapGenerator.renderTheme.matchWay(this, debugTagBox, (byte) 0, false, true);
}
tile.lineLayers = mLineLayers;
tile.polygonLayers = mPolyLayers;
tile.labels = mLabels;
mCurPolyLayer = null;
mCurLineLayer = null;
mLineLayers = null;
mPolyLayers = null;
mLabels = null;
return true;
}
private final Tag[] debugTagBox = { new Tag("debug", "box") };
private final Tag[] debugTagWay = { new Tag("debug", "way") };
private final Tag[] debugTagArea = { new Tag("debug", "area") };
private float mProjectionScaleFactor;
private static byte getValidLayer(byte layer) {
if (layer < 0) {
return 0;
@ -612,8 +586,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
float[] coords = mWayNodes;
long x = mCurrentTile.x;
long y = mCurrentTile.y;
long x = mCurrentTile.pixelX;
long y = mCurrentTile.pixelY + Tile.TILE_SIZE;
long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel;
float min = mSimplify;

File diff suppressed because it is too large Load Diff

View File

@ -82,9 +82,7 @@ class PolygonLayers {
// do not modify stencil buffer
glStencilMask(0);
// clip with depth mask
// GLES20.glEnable(GLES20.GL_DEPTH_TEST);
// glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
for (int c = 0; c < count; c++) {
PolygonLayer l = mFillPolys[c];
@ -139,13 +137,10 @@ class PolygonLayers {
if (blend)
glDisable(GL_BLEND);
// glDisable(GLES20.GL_DEPTH_TEST);
// glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
}
static PolygonLayer drawPolygons(PolygonLayer layer, int next,
float[] matrix, double zoom, float scale, short drawCount, boolean clip) {
float[] matrix, double zoom, float scale, boolean clip) {
int cnt = 0;
glUseProgram(polygonProgram);
@ -182,10 +177,8 @@ class PolygonLayers {
// clear stencilbuffer (tile region)
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
// draw depth clipper
if (first) {
// glEnable(GLES20.GL_DEPTH_TEST);
// glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
GLES20.glPolygonOffset(0, drawCount);
GLES20.glDepthMask(true);
GLES20.glDepthFunc(GLES20.GL_LESS);
}
@ -196,13 +189,16 @@ class PolygonLayers {
first = false;
GLES20.glDepthMask(false);
GLES20.glDepthFunc(GLES20.GL_EQUAL);
// glDisable(GLES20.GL_DEPTH_TEST);
}
// stencil op for stencil method polygon drawing
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
}
//
mFillPolys[cnt] = l;
// set stencil mask to draw to
@ -223,7 +219,7 @@ class PolygonLayers {
glDisable(GL_STENCIL_TEST);
if (clip && first)
drawDepthClip(drawCount);
drawDepthClip();
// required on GalaxyII, Android 2.3.3 (cant just VAA enable once...)
GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
@ -231,53 +227,16 @@ class PolygonLayers {
return l;
}
// static void drawStencilClip(byte drawCount) {
// // set stencil mask for line drawing... HACK!!!
// glColorMask(false, false, false, false);
//
// int c = drawCount % 16;
// // never pass the test, i.e. always apply first stencil op (sfail)
// // glStencilFunc(GLES20.GL_NEVER, drawCount, 0);
// glStencilFunc(GLES20.GL_NEVER, flipdabit[c], 0);
//
// // replace stencilbuffer
// glStencilMask(0xff);
//
// // set stencilbuffer for (tile region)
// glStencilOp(GLES20.GL_REPLACE, GLES20.GL_KEEP, GLES20.GL_KEEP);
// glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
//
// glStencilFunc(GL_EQUAL, flipdabit[c], 0xff);
// // do not modify stencil buffer
// glStencilMask(0);
//
// glColorMask(true, true, true, true);
// }
// this only increases the chance for the stencil buffer clip to work
// should check for clipping with depth buffer or sth
// private static short[] flipdabit = {
// 255, 254, 253, 251,
// 247, 239, 223, 191,
// 127, 63, 252, 250,
// 249, 243, 231, 207 };
static void drawDepthClip(short drawCount) {
static void drawDepthClip() {
glColorMask(false, false, false, false);
// glEnable(GLES20.GL_DEPTH_TEST);
// glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
GLES20.glPolygonOffset(0, drawCount);
GLES20.glDepthMask(true);
GLES20.glDepthFunc(GLES20.GL_LESS);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
GLES20.glDepthMask(false);
glColorMask(true, true, true, true);
GLES20.glDepthFunc(GLES20.GL_EQUAL);
}

View File

@ -18,7 +18,7 @@ package org.mapsforge.android.glrenderer;
class Shaders {
final static String lineVertexShader = ""
+ "precision mediump float; \n"
+ "precision mediump float;"
+ "uniform mat4 mvp;"
+ "attribute vec4 a_position;"
+ "attribute vec2 a_st;"
@ -32,7 +32,26 @@ class Shaders {
+ " v_st = u_width * a_st;"
+ "}";
final static String lineFragmentShader = ""
+ "precision mediump float;"
+ "uniform float u_wscale;"
+ "uniform float u_width;"
+ "uniform vec4 u_color;"
+ "varying vec2 v_st;"
+ "const float zero = 0.0;"
+ "void main() {"
+ " vec4 color = u_color;"
+ " float len;"
+ " if (v_st.t == zero)"
+ " len = abs(v_st.s);"
+ " else "
+ " len = length(v_st);"
+ " color.a *= smoothstep(zero, u_wscale, u_width - len);"
+ " gl_FragColor = color;"
+ "}";
// final static String lineFragmentShader = ""
// + "#extension GL_OES_standard_derivatives : enable\n"
// + "precision mediump float;\n"
// + "uniform float u_wscale;"
// + "uniform float u_width;"
@ -41,39 +60,18 @@ class Shaders {
// + "const float zero = 0.0;"
// + "void main() {"
// + " vec4 color = u_color;"
// + " float width = u_width;"
// + " float len;"
// + " if (v_st.t == zero)"
// + " len = abs(v_st.s);"
// + " else "
// + " len = length(v_st);"
// + " color.a *= smoothstep(zero, u_wscale, u_width - len);"
// + " vec2 st_width = fwidth(v_st);"
// + " float fuzz = max(st_width.s, st_width.t) * 1.5;"
// + " color.a *= smoothstep(zero, fuzz + u_wscale, u_width - len);"
// + " gl_FragColor = color;"
// + "}";
final static String lineFragmentShader = ""
+ "#extension GL_OES_standard_derivatives : enable\n"
+ "precision mediump float;\n"
+ "uniform float u_wscale;"
+ "uniform float u_width;"
+ "uniform vec4 u_color;"
+ "varying vec2 v_st;"
+ "const float zero = 0.0;"
+ "void main() {"
+ " vec4 color = u_color;"
+ " float width = u_width;"
+ " float len;"
+ " if (v_st.t == zero)"
+ " len = abs(v_st.s);"
+ " else "
+ " len = length(v_st);"
// + " if (u_width - len < 2.0){"
+ " vec2 st_width = fwidth(v_st);"
+ " float fuzz = max(st_width.s, st_width.t) * 1.5;"
+ " color.a *= smoothstep(zero, fuzz + u_wscale, u_width - len);"
// + " }"
+ " gl_FragColor = color;"
+ "}";
final static String polygonVertexShader = ""
+ "precision mediump float;"
+ "uniform mat4 mvp;"
@ -113,7 +111,7 @@ class Shaders {
+ "}";
// final static String lineVertexZigZagShader = ""
// + "precision mediump float; \n"
// + "precision mediump float;"
// + "uniform mat4 mvp;"
// + "attribute vec4 a_pos1;"
// + "attribute vec2 a_st1;"
@ -135,7 +133,7 @@ class Shaders {
// final static String lineFragmentShader = ""
// + "#extension GL_OES_standard_derivatives : enable\n"
// + "precision mediump float;\n"
// + "precision mediump float;"
// + "uniform vec2 u_mode;"
// + "uniform vec4 u_color;"
// + "varying vec2 v_st;"

View File

@ -23,7 +23,7 @@ public class ShortPool {
static private int count = 0;
static private int countAll = 0;
static synchronized void finish() {
static synchronized void init() {
count = 0;
countAll = 0;
pool = null;

View File

@ -45,7 +45,6 @@ public class TextRenderer {
private static int mFontPadY = 1;
private static int mBitmapFormat;
private static int mBitmapType;
private static ByteBuffer mByteBuffer;
private static ShortBuffer mShortBuffer;
private static TextTexture[] mTextures;
@ -57,9 +56,8 @@ public class TextRenderer {
private static int hTextVertex;
private static int hTextScale;
private static int hTextTextureCoord;
// private static int hTextUColor;
static Paint mPaint = new Paint(Color.BLACK);
private static Paint mPaint = new Paint(Color.BLACK);
private static boolean debug = false;
private static short[] debugVertices = {
@ -79,13 +77,24 @@ public class TextRenderer {
};
static boolean init(int numTextures) {
mBitmap = Bitmap
.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT, Bitmap.Config.ARGB_8888);
int bufferSize = numTextures
* MAX_LABELS * VERTICES_PER_SPRITE
* SHORTS_PER_VERTICE * (Short.SIZE / 8);
// if (mBitmap == null) {
mBitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT,
Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mBitmapFormat = GLUtils.getInternalFormat(mBitmap);
mBitmapType = GLUtils.getType(mBitmap);
ByteBuffer buf = ByteBuffer.allocateDirect(bufferSize)
.order(ByteOrder.nativeOrder());
mShortBuffer = buf.asShortBuffer();
// }
mTextProgram = GlUtils.createProgram(Shaders.textVertexShader,
Shaders.textFragmentShader);
@ -94,15 +103,6 @@ public class TextRenderer {
hTextScale = GLES20.glGetUniformLocation(mTextProgram, "scale");
hTextTextureCoord = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
int bufferSize = numTextures
* MAX_LABELS * VERTICES_PER_SPRITE
* SHORTS_PER_VERTICE * (Short.SIZE / 8);
mByteBuffer = ByteBuffer.allocateDirect(bufferSize)
.order(ByteOrder.nativeOrder());
mShortBuffer = mByteBuffer.asShortBuffer();
int[] textureIds = new int[numTextures];
TextTexture[] textures = new TextTexture[numTextures];
GLES20.glGenTextures(numTextures, textureIds, 0);
@ -136,24 +136,23 @@ public class TextRenderer {
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);
indices[i + 0] = (short) (j + 0);
indices[i + 1] = (short) (j + 0);
indices[i + 2] = (short) (j + 1);
indices[i + 3] = (short) (j + 3);
indices[i + 4] = (short) (j + 2);
indices[i + 5] = (short) (j + 2);
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);
// indices[i + 0] = (short) (j + 0);
// indices[i + 1] = (short) (j + 0);
// indices[i + 2] = (short) (j + 1);
// indices[i + 3] = (short) (j + 3);
// indices[i + 4] = (short) (j + 2);
// indices[i + 5] = (short) (j + 2);
}
ShortBuffer tmpIndices = mByteBuffer.asShortBuffer();
tmpIndices.put(indices, 0, len);
tmpIndices.flip();
mShortBuffer.clear();
mShortBuffer.put(indices, 0, len);
mShortBuffer.flip();
int[] mVboIds = new int[2];
GLES20.glGenBuffers(2, mVboIds, 0);
@ -162,13 +161,15 @@ public class TextRenderer {
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, len * (Short.SIZE / 8),
tmpIndices, GLES20.GL_STATIC_DRAW);
mShortBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
mShortBuffer.clear();
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, bufferSize,
mShortBuffer, GLES20.GL_DYNAMIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
return true;
}
@ -360,10 +361,13 @@ public class TextRenderer {
tex.length = pos;
tile.texture = tex;
tex.tile = tile;
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex.id);
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mBitmap,
mBitmapFormat, mBitmapType);
GLES20.glFlush();
return true;
}
@ -388,9 +392,7 @@ public class TextRenderer {
}
mShortBuffer.flip();
// Log.d(TAG, "compileTextures" + mFloatBuffer.remaining() + " " + offset);
// TODO use sub-bufferdata function
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, offset * (Short.SIZE / 8),
mShortBuffer);
}
@ -442,7 +444,7 @@ public class TextRenderer {
GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8)
+ 8);
GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, (tile.texture.length / 24) *
GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tile.texture.length / 24) *
INDICES_PER_SPRITE, GLES20.GL_UNSIGNED_SHORT, 0);
}
}

View File

@ -0,0 +1,152 @@
/*
* Copyright 2012 Hannes Janetzek
*
* 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 android.util.Log;
class TreeTile {
private static String TAG = "TreeTile";
private static TreeTile root;
// parent pointer is used to link pool items
private static TreeTile pool;
// TreeTile members
TreeTile parent;
final TreeTile[] child = new TreeTile[4];
int refs = 0;
byte id;
GLMapTile tile;
static void init() {
pool = null;
root = new TreeTile();
root.parent = root;
TreeTile t;
for (int i = 0; i < 200; i++) {
t = new TreeTile();
t.parent = pool;
pool = t;
}
}
static boolean remove(GLMapTile t) {
if (t.rel == null) {
Log.d(TAG, "already removed " + t);
return true;
}
TreeTile cur = t.rel;
TreeTile next;
for (; cur != root;) {
// keep pointer to parent
next = cur.parent;
cur.refs--;
// if current node has no children
if (cur.refs == 0) {
// unhook from parent
next.child[cur.id] = null;
// add item back to pool
cur.parent = pool;
pool = cur;
}
cur = next;
}
root.refs--;
t.rel.tile = null;
t.rel = null;
return true;
}
static TreeTile add(GLMapTile tile) {
int x = tile.tileX;
int y = tile.tileY;
int z = tile.zoomLevel;
TreeTile cur;
// if (x < 0 || x >= 1 << z) {
// Log.d(TAG, "invalid position");
// return null;
// }
// if (y < 0 || y >= 1 << z) {
// Log.d(TAG, "invalid position");
// return null;
// }
TreeTile leaf = root;
for (int level = z - 1; level >= 0; level--) {
int id = ((x >> level) & 1) | ((y >> level) & 1) << 1;
leaf.refs++;
cur = leaf.child[id];
if (cur != null) {
leaf = cur;
continue;
}
if (pool != null) {
cur = pool;
pool = pool.parent;
} else {
cur = new TreeTile();
}
cur.refs = 0;
cur.id = (byte) id;
cur.parent = leaf;
cur.parent.child[id] = cur;
leaf = cur;
}
leaf.refs++;
leaf.tile = tile;
tile.rel = leaf;
return leaf;
}
static GLMapTile getTile(int x, int y, int z) {
TreeTile leaf = root;
for (int level = z - 1; level >= 0; level--) {
leaf = leaf.child[((x >> level) & 1) | ((y >> level) & 1) << 1];
if (leaf == null)
return null;
if (level == 0) {
return leaf.tile;
}
}
return null;
}
}

View File

@ -25,10 +25,10 @@ final class WayDecorator {
// */
// private static final int DISTANCE_BETWEEN_SYMBOLS = 200;
/**
* Minimum distance in pixels before the way name is repeated.
*/
private static final int DISTANCE_BETWEEN_WAY_NAMES = 500;
// /**
// * Minimum distance in pixels before the way name is repeated.
// */
// private static final int DISTANCE_BETWEEN_WAY_NAMES = 500;
// /**
// * Distance in pixels to skip from both ends of a segment.

View File

@ -17,18 +17,19 @@ package org.mapsforge.android.input;
import org.mapsforge.android.MapView;
import org.mapsforge.android.MapViewPosition;
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.view.ScaleGestureDetector;
import android.view.animation.DecelerateInterpolator;
class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener {
private final MapView mMapView;
private MapViewPosition mMapPosition;
private float mCenterX;
private float mCenterY;
// private float mFocusX;
// private float mFocusY;
private float mScale;
private boolean mBeginScale;
// private boolean mScaling;
/**
* Creates a new ScaleListener for the given MapView.
*
@ -40,52 +41,104 @@ class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener {
}
@Override
public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
public boolean onScale(ScaleGestureDetector gd) {
float focusX = scaleGestureDetector.getFocusX();
float focusY = scaleGestureDetector.getFocusY();
mScale = scaleGestureDetector.getScaleFactor();
float focusX = gd.getFocusX();
float focusY = gd.getFocusY();
mScale = gd.getScaleFactor();
// mMapPosition.moveMap((focusX - mFocusX), (focusY - mFocusY));
// if (mScale > 1.001 || mScale < 0.999) {
mSumScale *= mScale;
mMapPosition.scaleMap(mScale,
focusX - mCenterX,
focusY - mCenterY);
mTimeEnd = SystemClock.elapsedRealtime();
if (!mBeginScale) {
if (mTimeEnd - mTimeStart > 100) {
mBeginScale = true;
mScale = mSumScale;
}
else
return true;
}
mMapPosition.scaleMap(mScale, focusX - mCenterX, focusY - mCenterY);
mMapView.redrawTiles();
// mScale = 1;
// mFocusX = focusX;
// mFocusY = focusY;
// }
// else if (Math.abs(focusX - mFocusX) > 0.5 || Math.abs(focusY - mFocusY) > 0.5) {
// mMapPosition.moveMap((focusX - mFocusX), (focusY - mFocusY));
//
// mFocusX = focusX;
// mFocusY = focusY;
// mScale = 1;
// mMapView.redrawTiles();
// }
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
private long mTimeStart;
private long mTimeEnd;
private float mSumScale;
@Override
public boolean onScaleBegin(ScaleGestureDetector gd) {
mTimeEnd = mTimeStart = SystemClock.elapsedRealtime();
mSumScale = 1;
mBeginScale = false;
mCenterX = mMapView.getWidth() >> 1;
mCenterY = mMapView.getHeight() >> 1;
// mFocusX = scaleGestureDetector.getFocusX();
// mFocusY = scaleGestureDetector.getFocusY();
mScale = 1;
mMapPosition = mMapView.getMapPosition();
// mScaling = false;
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
// do nothing
public void onScaleEnd(ScaleGestureDetector gd) {
// Log.d("ScaleListener", "Sum " + mSumScale + " " + (mTimeEnd - mTimeStart));
if (mTimer == null && mTimeEnd - mTimeStart < 150
&& (mSumScale < 0.99 || mSumScale > 1.01)) {
mPrevScale = 0;
mZooutOut = mSumScale < 0.99;
mTimer = new CountDownTimer((int) mScaleDuration, 30) {
@Override
public void onTick(long tick) {
scale(tick);
}
@Override
public void onFinish() {
scale(0);
}
}.start();
}
}
private DecelerateInterpolator mBounce = new DecelerateInterpolator();
private float mPrevScale;
private CountDownTimer mTimer;
boolean mZooutOut;
private final float mScaleDuration = 350;
boolean scale(long tick) {
if (mPrevScale >= 1) {
mTimer = null;
return false;
}
float adv = (mScaleDuration - tick) / mScaleDuration;
adv = mBounce.getInterpolation(adv);
float scale = adv - mPrevScale;
mPrevScale += scale;
if (mZooutOut) {
scale = 1 - scale;
} else {
scale = 1 + scale;
}
mMapPosition.scaleMap(scale, 0, 0);
mMapView.redrawTiles();
if (tick == 0)
mTimer = null;
return true;
}
}

View File

@ -15,16 +15,17 @@
package org.mapsforge.android.input;
import org.mapsforge.android.MapView;
import org.mapsforge.android.MapViewPosition;
import org.mapsforge.core.Tile;
import android.content.Context;
import android.os.CountDownTimer;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller;
/**
@ -33,15 +34,15 @@ import android.widget.Scroller;
public class TouchHandler {
private static final int INVALID_POINTER_ID = -1;
/**
* is pritected correct? share MapView with inner class
*/
protected final MapView mMapView;
protected final MapViewPosition mMapPosition;
private final float mMapMoveDelta;
private boolean mMoveThresholdReached;
private float mPreviousPositionX;
private float mPreviousPositionY;
private float mPosX;
private float mPosY;
private float mAngle;
private int mActivePointerId;
private final ScaleGestureDetector mScaleGestureDetector;
@ -56,11 +57,13 @@ public class TouchHandler {
public TouchHandler(Context context, MapView mapView) {
ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
mMapView = mapView;
mMapPosition = mapView.getMapPosition();
mMapMoveDelta = viewConfiguration.getScaledTouchSlop();
mActivePointerId = INVALID_POINTER_ID;
mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener(
mMapView));
mGestureDetector = new GestureDetector(new MapGestureDetector(mMapView));
mGestureDetector = new GestureDetector(context, new MapGestureDetector(mMapView));
}
private static int getAction(MotionEvent motionEvent) {
@ -72,22 +75,30 @@ public class TouchHandler {
return true;
}
private boolean onActionDown(MotionEvent motionEvent) {
mPreviousPositionX = motionEvent.getX();
mPreviousPositionY = motionEvent.getY();
private boolean onActionDown(MotionEvent event) {
mPosX = event.getX();
mPosY = event.getY();
mMoveThresholdReached = false;
// save the ID of the pointer
mActivePointerId = motionEvent.getPointerId(0);
mActivePointerId = event.getPointerId(0);
// Log.d("...", "set active pointer" + mActivePointerId);
return true;
}
private boolean onActionMove(MotionEvent motionEvent) {
int pointerIndex = motionEvent.findPointerIndex(mActivePointerId);
private boolean mScaling = false;
private boolean onActionMove(MotionEvent event) {
int pointerIndex = event.findPointerIndex(mActivePointerId);
// calculate the distance between previous and current position
float moveX = motionEvent.getX(pointerIndex) - mPreviousPositionX;
float moveY = motionEvent.getY(pointerIndex) - mPreviousPositionY;
float moveX = event.getX(pointerIndex) - mPosX;
float moveY = event.getY(pointerIndex) - mPosY;
boolean scaling = mScaleGestureDetector.isInProgress();
if (!mScaling) {
mScaling = scaling;
}
if (!scaling && !mMoveThresholdReached) {
if (Math.abs(moveX) > 3 * mMapMoveDelta
@ -97,36 +108,57 @@ public class TouchHandler {
mMoveThresholdReached = true;
// save the position of the event
mPreviousPositionX = motionEvent.getX(pointerIndex);
mPreviousPositionY = motionEvent.getY(pointerIndex);
mPosX = event.getX(pointerIndex);
mPosY = event.getY(pointerIndex);
}
return true;
}
// if (multi > 0) {
// double dx = event.getX(0) - event.getX(1);
// double dy = event.getY(0) - event.getY(1);
// double rad = Math.atan2(dy, dx);
// float angle = (float) Math.toDegrees(rad);
// mMapPosition.rotateMap(angle - mAngle);
// mAngle = angle;
// mMapView.redrawTiles();
// }
// save the position of the event
mPreviousPositionX = motionEvent.getX(pointerIndex);
mPreviousPositionY = motionEvent.getY(pointerIndex);
mPosX = event.getX(pointerIndex);
mPosY = event.getY(pointerIndex);
if (scaling) {
return true;
}
mMapView.getMapPosition().moveMap(moveX, moveY);
mMapPosition.moveMap(moveX, moveY);
mMapView.redrawTiles();
return true;
}
// private boolean onActionPointerDown(MotionEvent motionEvent) {
// longPressDetector.pressStop();
// multiTouchDownTime = motionEvent.getEventTime();
// return true;
// }
private int multi = 0;
private boolean onActionPointerDown(MotionEvent event) {
// longPressDetector.pressStop();
// multiTouchDownTime = motionEvent.getEventTime();
multi++;
if (multi == 1) {
double dx = event.getX(0) - event.getX(1);
double dy = event.getY(0) - event.getY(1);
double rad = Math.atan2(dy, dx);
mAngle = (float) Math.toDegrees(rad);
}
return true;
}
private boolean onActionPointerUp(MotionEvent motionEvent) {
// extract the index of the pointer that left the touch sensor
int pointerIndex = (motionEvent.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
if (motionEvent.getPointerId(pointerIndex) == mActivePointerId) {
// the active pointer has gone up, choose a new one
if (pointerIndex == 0) {
@ -135,19 +167,12 @@ public class TouchHandler {
pointerIndex = 0;
}
// save the position of the event
mPreviousPositionX = motionEvent.getX(pointerIndex);
mPreviousPositionY = motionEvent.getY(pointerIndex);
mPosX = motionEvent.getX(pointerIndex);
mPosY = motionEvent.getY(pointerIndex);
mActivePointerId = motionEvent.getPointerId(pointerIndex);
}
multi--;
// calculate the time difference since the pointer has gone down
// long multiTouchTime = motionEvent.getEventTime() -
// multiTouchDownTime;
// if (multiTouchTime < doubleTapTimeout) {
// // multi-touch tap event, zoom out
// previousEventTap = false;
// mapView.zoom((byte) -1);
// }
return true;
}
@ -157,83 +182,53 @@ public class TouchHandler {
* @return ...
*/
private boolean onActionUp(MotionEvent motionEvent) {
// longPressDetector.pressStop();
// int pointerIndex = motionEvent.findPointerIndex(mActivePointerId);
mActivePointerId = INVALID_POINTER_ID;
// if (mMoveThresholdReached // || longPressDetector.isEventHandled()
// ) {
// mPreviousEventTap = false;
// } else {
// if (mPreviousEventTap) {
//
// } else {
// mPreviousEventTap = true;
// }
//
// // store the position and the time of this tap event
// mPreviousTapX = motionEvent.getX(pointerIndex);
// mPreviousTapY = motionEvent.getY(pointerIndex);
// mPreviousTapTime = motionEvent.getEventTime();
//
// }
mScaling = false;
return true;
}
private long lastRun = 0;
/**
* @param motionEvent
* @param event
* ...
* @return ...
*/
public boolean handleMotionEvent(MotionEvent motionEvent) {
public boolean handleMotionEvent(MotionEvent event) {
// workaround for a bug in the ScaleGestureDetector, see Android issue
// #12976
if (motionEvent.getAction() != MotionEvent.ACTION_MOVE
|| motionEvent.getPointerCount() > 1) {
mScaleGestureDetector.onTouchEvent(motionEvent);
}
mGestureDetector.onTouchEvent(motionEvent);
// if () {
// // mActivePointerId = INVALID_POINTER_ID;
// // return true;
// if (event.getAction() != MotionEvent.ACTION_MOVE
// || event.getPointerCount() > 1) {
mScaleGestureDetector.onTouchEvent(event);
// }
int action = getAction(motionEvent);
if (!mScaling)
mGestureDetector.onTouchEvent(event);
int action = getAction(event);
boolean ret = false;
if (action == MotionEvent.ACTION_DOWN) {
ret = onActionDown(motionEvent);
ret = onActionDown(event);
} else if (action == MotionEvent.ACTION_MOVE) {
ret = onActionMove(motionEvent);
ret = onActionMove(event);
} else if (action == MotionEvent.ACTION_UP) {
ret = onActionUp(motionEvent);
ret = onActionUp(event);
} else if (action == MotionEvent.ACTION_CANCEL) {
ret = onActionCancel();
// } else if (action == MotionEvent.ACTION_POINTER_DOWN) {
// return onActionPointerDown(motionEvent);
} else if (action == MotionEvent.ACTION_POINTER_DOWN) {
return onActionPointerDown(event);
} else if (action == MotionEvent.ACTION_POINTER_UP) {
ret = onActionPointerUp(motionEvent);
ret = onActionPointerUp(event);
}
// if (ret) {
// // throttle input
// long diff = SystemClock.uptimeMillis() - lastRun;
// if (diff < 16 && diff > 5) {
// // Log.d("", "" + diff);
// SystemClock.sleep(16 - diff);
// }
// lastRun = SystemClock.uptimeMillis();
// }
return ret;
}
class MapGestureDetector extends SimpleOnGestureListener {
private Scroller mScroller;
private float mPrevX, mPrevY;
private float mPrevX, mPrevY, mPrevScale;
private CountDownTimer mTimer = null;
private boolean fling = false;
public MapGestureDetector(MapView mapView) {
mScroller = new Scroller(mapView.getContext(),
@ -242,12 +237,17 @@ public class TouchHandler {
@Override
public boolean onDown(MotionEvent e) {
mScroller.forceFinished(true);
if (fling) {
mScroller.forceFinished(true);
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
fling = false;
}
// Log.d("mapsforge", "onDown");
return true;
}
@ -256,11 +256,12 @@ public class TouchHandler {
return false;
}
mScroller.computeScrollOffset();
float moveX = mScroller.getCurrX() - mPrevX;
float moveY = mScroller.getCurrY() - mPrevY;
if (moveX >= 1 || moveY >= 1 || moveX <= -1 || moveY <= -1) {
mMapView.getMapPosition().moveMap(moveX, moveY);
mMapPosition.moveMap(moveX, moveY);
mMapView.redrawTiles();
mPrevX = mScroller.getCurrX();
mPrevY = mScroller.getCurrY();
@ -271,8 +272,8 @@ public class TouchHandler {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
int w = Tile.TILE_SIZE * 10;
int h = Tile.TILE_SIZE * 10;
int w = Tile.TILE_SIZE * 20;
int h = Tile.TILE_SIZE * 20;
mPrevX = 0;
mPrevY = 0;
@ -283,12 +284,12 @@ public class TouchHandler {
mScroller.fling(0, 0, Math.round(velocityX) / 2, Math.round(velocityY) / 2,
-w, w, -h, h);
// animate for two seconds
mTimer = new CountDownTimer(2000, 40) {
mTimer = new CountDownTimer(1500, 50) {
@Override
public void onTick(long tick) {
if (!scroll())
cancel();
scroll();
}
@Override
@ -296,21 +297,61 @@ public class TouchHandler {
// do nothing
}
}.start();
fling = true;
return true;
}
private DecelerateInterpolator mBounce = new DecelerateInterpolator();
@Override
public void onLongPress(MotionEvent e) {
// mMapView.zoom((byte) 1);
Log.d("mapsforge", "long press");
// return true;
// Log.d("mapsforge", "long press");
}
private final float mScaleDuration = 300;
boolean scale(long tick) {
fling = true;
if (mPrevScale >= 1)
return false;
float adv = (mScaleDuration - tick) / mScaleDuration;
adv = mBounce.getInterpolation(adv);
float scale = adv - mPrevScale;
mPrevScale += scale;
scale += 1;
adv += 1;
if (scale > 1) {
mMapPosition.scaleMap(scale, mPrevX / adv, mPrevY / adv);
mMapView.redrawTiles();
}
return true;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
mMapView.zoom((byte) 1);
Log.d("mapsforge", "double tap");
// Log.d("mapsforge", "double tap");
mPrevX = (e.getX(0) - (mMapView.getWidth() >> 1)) * 2f;
mPrevY = (e.getY(0) - (mMapView.getHeight() >> 1)) * 2f;
mPrevScale = 0;
mTimer = new CountDownTimer((int) mScaleDuration, 30) {
@Override
public void onTick(long tick) {
scale(tick);
}
@Override
public void onFinish() {
scale(0);
}
}.start();
return true;
}
}

View File

@ -29,11 +29,11 @@ public interface IMapGenerator {
/**
* Called when a job needs to be executed.
*
* @param mapGeneratorJob
* @param tile
* the job that should be executed.
* @return true if the job was executed successfully, false otherwise.
*/
boolean executeJob(MapGeneratorJob mapGeneratorJob);
boolean executeJob(MapTile tile);
/**
* @param mapDatabase

View File

@ -1,82 +0,0 @@
/*
* 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.mapgenerator;
/**
* A JobParameters instance is a simple DTO to store the rendering parameters for a job.
*/
public class JobParameters {
/**
* The render theme which should be used.
*/
public final Theme theme;
/**
* The text scale factor which should applied to the render theme.
*/
public final float textScale;
private final int mHashCodeValue;
/**
* @param theme
* render theme which should be used.
* @param textScale
* the text scale factor which should applied to the render theme.
*/
public JobParameters(Theme theme, float textScale) {
this.theme = theme;
this.textScale = textScale;
mHashCodeValue = calculateHashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof JobParameters)) {
return false;
}
JobParameters other = (JobParameters) obj;
if (theme == null) {
if (other.theme != null) {
return false;
}
} else if (!theme.equals(other.theme)) {
return false;
}
if (Float.floatToIntBits(textScale) != Float.floatToIntBits(other.textScale)) {
return false;
}
return true;
}
@Override
public int hashCode() {
return mHashCodeValue;
}
/**
* @return the hash code of this object.
*/
private int calculateHashCode() {
int result = 7;
result = 31 * result + ((theme == null) ? 0 : theme.hashCode());
result = 31 * result + Float.floatToIntBits(textScale);
return result;
}
}

View File

@ -17,54 +17,29 @@ package org.mapsforge.android.mapgenerator;
import java.util.ArrayList;
import java.util.PriorityQueue;
import org.mapsforge.android.MapView;
import android.os.SystemClock;
/**
* A JobQueue keeps the list of pending jobs for a MapView and prioritizes them.
*/
public class JobQueue {
private static final int INITIAL_CAPACITY = 128;
private static final int INITIAL_CAPACITY = 64;
private final MapView mMapView;
private PriorityQueue<MapGeneratorJob> mPriorityQueue;
private boolean mScheduleNeeded;
private PriorityQueue<MapTile> mPriorityQueue;
/**
* @param mapView
* the MapView whose jobs should be organized.
*/
public JobQueue(MapView mapView) {
mMapView = mapView;
mPriorityQueue = new PriorityQueue<MapGeneratorJob>(INITIAL_CAPACITY);
public JobQueue() {
mPriorityQueue = new PriorityQueue<MapTile>(INITIAL_CAPACITY);
}
/**
* Adds the given job to this queue. Does nothing if the given job is already in this queue.
*
* @param mapGeneratorJob
* @param tiles
* the job to be added to this queue.
*/
// public synchronized void addJob(MapGeneratorJob mapGeneratorJob) {
// if (!mPriorityQueue.contains(mapGeneratorJob))
// // priorityQueue.remove(mapGeneratorJob);
// {
// //mapGeneratorJob.tile.isLoading = true;
// mPriorityQueue.offer(mapGeneratorJob);
// }
// }
/**
* @param jobs
* the job to be added to this queue.
*/
public synchronized void setJobs(ArrayList<MapGeneratorJob> jobs) {
public synchronized void setJobs(ArrayList<MapTile> tiles) {
mPriorityQueue.clear();
for (MapGeneratorJob job : jobs)
mPriorityQueue.offer(job);
// priorityQueue.addAll(jobs);
mScheduleNeeded = true;
mPriorityQueue.addAll(tiles);
// for (int i = 0, n = tiles.size(); i < n; i++)
// mPriorityQueue.offer(tiles.get(i));
}
/**
@ -84,39 +59,11 @@ public class JobQueue {
/**
* @return the most important job from this queue or null, if empty.
*/
public synchronized MapGeneratorJob poll() {
if (mScheduleNeeded) {
mScheduleNeeded = false;
schedule();
}
return mPriorityQueue.poll();
public synchronized MapTile poll() {
MapTile tile = mPriorityQueue.poll();
if (tile != null)
tile.isLoading = true;
return tile;
}
/**
* Request a scheduling of all jobs that are currently in this queue.
*/
public synchronized void requestSchedule() {
mScheduleNeeded = true;
}
/**
* Schedules all jobs in this queue.
*/
private void schedule() {
PriorityQueue<MapGeneratorJob> tempJobQueue = new PriorityQueue<MapGeneratorJob>(
INITIAL_CAPACITY);
TileScheduler.time = SystemClock.uptimeMillis();
TileScheduler.mapPosition = mMapView.getMapPosition().getMapPosition();
while (!mPriorityQueue.isEmpty()) {
MapGeneratorJob mapGeneratorJob = mPriorityQueue.poll();
double priority = TileScheduler.getPriority(mapGeneratorJob, mMapView);
mapGeneratorJob.setPriority(priority);
tempJobQueue.offer(mapGeneratorJob);
}
mPriorityQueue = tempJobQueue;
}
}

View File

@ -46,7 +46,7 @@ public final class MapDatabaseFactory {
String mapDatabaseName = attributeSet.getAttributeValue(null,
MAP_DATABASE_ATTRIBUTE_NAME);
if (mapDatabaseName == null) {
return MapDatabases.POSTGIS_READER;
return MapDatabases.PBMAP_READER;
}
return MapDatabases.valueOf(mapDatabaseName);

View File

@ -1,43 +0,0 @@
/*
* 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.mapgenerator;
import org.mapsforge.android.utils.PausableThread;
public class MapDownloader extends PausableThread {
private static final String THREAD_NAME = "MapDownloader";
@Override
protected void doWork() {
// TODO Auto-generated method stub
}
@Override
protected boolean hasWork() {
// TODO Auto-generated method stub
return false;
}
@Override
protected String getThreadName() {
return THREAD_NAME;
}
@Override
protected int getThreadPriority() {
return (Thread.NORM_PRIORITY + Thread.MIN_PRIORITY) / 2;
}
}

View File

@ -1,182 +0,0 @@
/*
* 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.mapgenerator;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import org.mapsforge.android.DebugSettings;
import android.graphics.Bitmap;
/**
* A MapGeneratorJob holds all immutable rendering parameters for a single map image together with a mutable priority
* field, which indicates the importance of this job.
*/
public class MapGeneratorJob implements Comparable<MapGeneratorJob>, Serializable {
private static final long serialVersionUID = 1L;
/**
* The debug settings for this job.
*/
public final DebugSettings debugSettings;
/**
* The rendering parameters for this job.
*/
// public final JobParameters jobParameters;
/**
* The tile which should be generated.
*/
public final MapTile tile;
private transient int mHashCodeValue;
private transient double mPriority;
/**
* bitmap passed to renderer
*/
private Bitmap mBitmap;
/**
* @return ...
*/
public Bitmap getBitmap() {
return mBitmap;
}
/**
* @param bitmap
* ..
*/
public void setBitmap(Bitmap bitmap) {
mBitmap = bitmap;
}
private float mScale;
/**
* @return scale the tile is rendered with
*/
public float getScale() {
return mScale;
}
/**
* @param _scale
* for the tile to be rendered
*/
public void setScale(float _scale) {
mScale = _scale;
}
/**
* Creates a new job for a MapGenerator with the given parameters.
*
* @param _tile
* the tile which should be generated.
* @param _jobParameters
* the rendering parameters for this job.
* @param _debugSettings
* the debug settings for this job.
*/
public MapGeneratorJob(MapTile _tile, JobParameters _jobParameters,
DebugSettings _debugSettings) {
tile = _tile;
// jobParameters = _jobParameters;
debugSettings = _debugSettings;
calculateTransientValues();
}
@Override
public int compareTo(MapGeneratorJob o) {
if (mPriority < o.mPriority) {
return -1;
} else if (mPriority > o.mPriority) {
return 1;
}
return 0;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof MapGeneratorJob)) {
return false;
}
MapGeneratorJob other = (MapGeneratorJob) obj;
if (debugSettings == null) {
if (other.debugSettings != null) {
return false;
}
} else if (!debugSettings.equals(other.debugSettings)) {
return false;
}
// if (jobParameters == null) {
// if (other.jobParameters != null) {
// return false;
// }
// } else if (!jobParameters.equals(other.jobParameters)) {
// return false;
// }
if (tile == null) {
if (other.tile != null) {
return false;
}
} else if (!tile.equals(other.tile)) {
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 + ((debugSettings == null) ? 0 : debugSettings.hashCode());
// result = 31 * result + ((jobParameters == null) ? 0 : jobParameters.hashCode());
result = 31 * result + ((tile == null) ? 0 : tile.hashCode());
return result;
}
/**
* Calculates the values of some transient variables.
*/
private void calculateTransientValues() {
mHashCodeValue = calculateHashCode();
}
private void readObject(ObjectInputStream objectInputStream) throws IOException,
ClassNotFoundException {
objectInputStream.defaultReadObject();
calculateTransientValues();
}
void setPriority(double priority) {
mPriority = priority;
}
}

View File

@ -19,7 +19,7 @@ import org.mapsforge.core.Tile;
/**
*
*/
public class MapTile extends Tile {
public class MapTile extends Tile implements Comparable<MapTile> {
/**
* tile is loaded and ready for drawing. (set and used by render thread after uploading data to gl).
*/
@ -53,7 +53,17 @@ public class MapTile extends Tile {
* @param zoomLevel
* ..
*/
public MapTile(long tileX, long tileY, byte zoomLevel) {
public MapTile(int tileX, int tileY, byte zoomLevel) {
super(tileX, tileY, zoomLevel);
}
@Override
public int compareTo(MapTile o) {
if (this.distance < o.distance) {
return -1;
} else if (this.distance > o.distance) {
return 1;
}
return 0;
}
}

View File

@ -62,15 +62,15 @@ public class MapWorker extends PausableThread {
@Override
protected void doWork() {
MapGeneratorJob mapGeneratorJob = mJobQueue.poll();
MapTile tile = mJobQueue.poll();
if (mMapGenerator == null || mapGeneratorJob == null)
if (mMapGenerator == null || tile == null)
return;
boolean success = mMapGenerator.executeJob(mapGeneratorJob);
boolean success = mMapGenerator.executeJob(tile);
if (!isInterrupted() && success) {
mMapRenderer.passTile(mapGeneratorJob);
mMapRenderer.passTile(tile);
}
}

View File

@ -18,9 +18,6 @@ import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.Serializable;
/**
* A JobTheme defines the render theme which is used for a {@link MapGeneratorJob}.
*/
public interface Theme extends Serializable {
/**
* @return an InputStream to read the render theme data from.

View File

@ -1,84 +0,0 @@
/*
* 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.mapgenerator;
/**
* @author jeff
*/
public class TileCacheKey {
long x, y;
byte z;
int hash;
/**
*
*/
public TileCacheKey() {
}
/**
* @param key
* create new TileCacheKey for key
*/
public TileCacheKey(TileCacheKey key) {
this.x = key.x;
this.y = key.y;
this.z = key.z;
this.hash = key.hash;
}
/**
* @param x
* Position
* @param y
* Position
* @param z
* Position
*/
public TileCacheKey(long x, long y, byte z) {
this.x = x;
this.y = y;
this.z = z;
hash = 7 * z + 31 * ((int) (x ^ (x >>> 32)) + 31 * (int) (y ^ (y >>> 32)));
}
/**
* @param x
* Position
* @param y
* Position
* @param z
* Position
* @return self
*/
public TileCacheKey set(long x, long y, byte z) {
this.x = x;
this.y = y;
this.z = z;
hash = 7 * z + 31 * ((int) (x ^ (x >>> 32)) + 31 * (int) (y ^ (y >>> 32)));
return this;
}
@Override
public boolean equals(Object obj) {
TileCacheKey other = (TileCacheKey) obj;
return (x == other.x && y == other.y && z == other.z);
}
@Override
public int hashCode() {
return hash;
}
}

View File

@ -1,68 +0,0 @@
/*
* 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.mapgenerator;
import org.mapsforge.android.MapView;
import org.mapsforge.core.MapPosition;
final class TileScheduler {
static long time;
static MapPosition mapPosition;
/**
* Calculates the priority for the given tile based on the current position and zoom level of the supplied MapView.
* The smaller the distance from the tile center to the MapView center, the higher its priority. If the zoom level
* of a tile differs from the zoom level of the MapView, its priority decreases.
*
* @param mapGeneratorJob
* the tile whose priority should be calculated.
* @param mapView
* the MapView whose current position and zoom level define the priority of the tile.
* @return the current priority of the tile. A smaller number means a higher priority.
*/
static double getPriority(MapGeneratorJob mapGeneratorJob, MapView mapView) {
MapTile tile = mapGeneratorJob.tile;
// if (tile.isDrawn) {
// long diff = time - tile.loadTime;
//
// // check.. just in case
// if (diff > 0.0) {
// return (10000.0f / diff) * (tile.isVisible ? 1 : 5); // * tile.distance;
// }
// }
// // calculate the center coordinates of the tile
// double tileCenterLongitude = MercatorProjection.pixelXToLongitude(tile.getCenterX(), tileZoomLevel);
// double tileCenterLatitude = MercatorProjection.pixelYToLatitude(tile.getCenterY(), tileZoomLevel);
//
// // calculate the Euclidian distance from the MapView center to the tile
// // center
// GeoPoint geoPoint = mapPosition.geoPoint;
// double longitudeDiff = geoPoint.getLongitude() - tileCenterLongitude;
// double latitudeDiff = geoPoint.getLatitude() - tileCenterLatitude;
//
// return Math.sqrt(longitudeDiff * longitudeDiff + latitudeDiff * latitudeDiff)
// * (tile.visible ? 1.0 : 1000.0);
// }
return tile.distance / 1000.0;
}
private TileScheduler() {
throw new IllegalStateException();
}
}

View File

@ -31,6 +31,8 @@ public interface IRenderCallback {
*
* @param area
* ...
* @param level
* ...
*/
void renderArea(Area area, int level);
@ -83,6 +85,8 @@ public interface IRenderCallback {
*
* @param line
* ...
* @param level
* ...
*/
void renderWay(Line line, int level);

View File

@ -27,7 +27,9 @@ public enum InternalRenderTheme implements Theme {
*
* @see <a href="http://wiki.openstreetmap.org/wiki/Osmarender">Osmarender</a>
*/
OSMARENDER("/org/mapsforge/android/rendertheme/osmarender/osmarender.xml");
OSMARENDER("/org/mapsforge/android/rendertheme/osmarender/osmarender.xml"),
TRONRENDER("/org/mapsforge/android/rendertheme/osmarender/tronrender.xml");
private final String mPath;

View File

@ -38,7 +38,8 @@ class PositiveRule extends Rule {
@Override
boolean matchesNode(Tag[] tags, byte zoomLevel) {
return (mElement != Element.WAY)
&& mZoomMin <= zoomLevel && mZoomMax >= zoomLevel
&& mZoomMin <= zoomLevel
&& mZoomMax >= zoomLevel
&& (mKeyMatcher == null || mKeyMatcher.matches(tags))
&& (mValueMatcher == null || mValueMatcher.matches(tags));
}
@ -46,7 +47,8 @@ class PositiveRule extends Rule {
@Override
boolean matchesWay(Tag[] tags, byte zoomLevel, int closed) {
return (mElement != Element.NODE)
&& mZoomMin <= zoomLevel && mZoomMax >= zoomLevel
&& mZoomMin <= zoomLevel
&& mZoomMax >= zoomLevel
&& (mClosed == closed || mClosed == Closed.ANY)
&& (mKeyMatcher == null || mKeyMatcher.matches(tags))
&& (mValueMatcher == null || mValueMatcher.matches(tags));

View File

@ -138,8 +138,7 @@ public class RenderTheme {
* @return ...
*/
public synchronized RenderInstruction[] matchNode(IRenderCallback renderCallback,
Tag[] tags,
byte zoomLevel) {
Tag[] tags, byte zoomLevel) {
RenderInstruction[] renderInstructions = null;
@ -189,9 +188,8 @@ public class RenderTheme {
* @return currently processed render instructions
*/
public synchronized RenderInstruction[] matchWay(IRenderCallback renderCallback,
Tag[] tags,
byte zoomLevel,
boolean closed, boolean render) {
Tag[] tags, byte zoomLevel, boolean closed, boolean render) {
RenderInstruction[] renderInstructions = null;
LRUCache<MatchingCacheKey, RenderInstruction[]> matchingCache;
@ -205,6 +203,7 @@ public class RenderTheme {
matchingCacheKey = new MatchingCacheKey(tags, zoomLevel);
boolean found = matchingCache.containsKey(matchingCacheKey);
if (found) {
renderInstructions = matchingCache.get(matchingCacheKey);
} else {

View File

@ -25,9 +25,9 @@ import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import org.mapsforge.android.rendertheme.renderinstruction.Area;
import org.mapsforge.android.rendertheme.renderinstruction.AreaLevel;
import org.mapsforge.android.rendertheme.renderinstruction.Caption;
import org.mapsforge.android.rendertheme.renderinstruction.Circle;
import org.mapsforge.android.rendertheme.renderinstruction.AreaLevel;
import org.mapsforge.android.rendertheme.renderinstruction.Line;
import org.mapsforge.android.rendertheme.renderinstruction.LineSymbol;
import org.mapsforge.android.rendertheme.renderinstruction.PathText;
@ -40,6 +40,8 @@ import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
/**
* SAX2 handler to parse XML render theme files.
*/
@ -195,7 +197,7 @@ public class RenderThemeHandler extends DefaultHandler {
// System.out.println("add style: " + line.style + " from " + style);
}
else {
// System.out.println("couldnt check the style yo! " + style);
Log.d("...", "this aint no style! " + style);
}
} else {
Line line = Line.create(null, localName, attributes, 0, false);
@ -266,6 +268,8 @@ public class RenderThemeHandler extends DefaultHandler {
mCurrentRule.addRenderingInstruction(newLine);
}
else
Log.d("...", "styles not a line! " + style);
}
} else if (ELEMENT_NAME_USE_STYLE_OUTLINE.equals(localName)) {
checkState(localName, Element.RENDERING_INSTRUCTION);
@ -274,6 +278,8 @@ public class RenderThemeHandler extends DefaultHandler {
Line line = (Line) tmpStyleHash.get("o" + style);
if (line != null && line.outline)
mCurrentRule.addRenderingInstruction(line);
else
Log.d("...", "styles not bad, but this aint no outline! " + style);
}
} else if (ELEMENT_NAME_USE_STYLE_AREA.equals(localName)) {
checkState(localName, Element.RENDERING_INSTRUCTION);
@ -283,6 +289,8 @@ public class RenderThemeHandler extends DefaultHandler {
if (area != null)
mCurrentRule.addRenderingInstruction(new AreaLevel(area,
mLevel++));
else
Log.d("...", "this aint no style inna di area! " + style);
}
} else if (ELEMENT_NAME_USE_STYLE_PATH_TEXT.equals(localName)) {
checkState(localName, Element.RENDERING_INSTRUCTION);
@ -291,6 +299,8 @@ public class RenderThemeHandler extends DefaultHandler {
PathText pt = (PathText) tmpStyleHash.get("t" + style);
if (pt != null)
mCurrentRule.addRenderingInstruction(pt);
else
Log.d("...", "this aint no path text style! " + style);
}
} else {
throw new SAXException("unknown element: " + localName);

View File

@ -485,7 +485,7 @@
</rule>
<!-- outline 1 - 4 -->
<style-outline name="1" stroke="#404040" width="0.025"/>
<style-outline name="1" stroke="#ee605020" width="0.02"/>
<!-- <style-outline name="1" stroke="#404030"/> -->
<style-outline name="2" stroke="#c0c0c0" />
<style-outline name="primary" stroke="#7f7700" width="0.025"/>

View File

@ -0,0 +1,992 @@
<?xml version="1.0" encoding="UTF-8"?>
<rendertheme xmlns="http://mapsforge.org/renderTheme"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://mapsforge.org/renderTheme ../renderTheme.xsd"
version="1" map-background="#050508">
<style-pathtext name="road" k="name" font-style="bold" font-size="18" stroke="#606050" fill="#eeffee" stroke-width="2.5" />
<style-pathtext name="major-road" k="name" font-style="bold" font-size="19" fill="#e2cf5d" stroke="#101010" stroke-width="2.5" />
<style-area name="residential" fill="#ff0000" fade="10"/>
<style-area name="railway|industrial" fill="#f2eeef" fade="10"/>
<!-- "#f0fae7" mint green -->
<style-area name="farmland" fill="#fff8bf" fade="11" />
<!-- fade out at z=7, blend over to 'blend-fill' in z=11 -->
<style-area name="forest|wood" fill="#151806" fade="7" blend="11" blend-fill="#1e2205"/>
<!-- grass|meadow|garden|grassland|scrub -->
<style-area name="greens" fill="#33390c" fade="10" />
<!-- marsh|wetland|nature_reserve -->
<style-area name="greens2" fill="#627100" fade="12" />
<!-- park|common|green|cemetery|golf_course|dog_park -->
<style-area name="park" fill="#627100" fade="11" />
<!-- de:Kleingartengebiet -->
<style-area name="allotments" fill="#efeae0" fade="12" />
<!-- de:Steinbruch, Schotter-, Kies-, Sand- und Tongrube -->
<style-area name="quarry" fill="#ddddcc" fade="10" />
<style-area name="military" fill="#eeedea" fade="10"/>
<style-line name="residential" stroke="#ffffff" width="1.0" blur="1.0" fade="13"/>
<style-line name="residential:bridge" from="residential" cap="square"/>
<!-- when inheriting another style with 'from' then 'witdth' is meant relative to the parent -->
<style-line name="pedestrian" from="residential" width="-0.4"/>
<style-line name="pedestrian:bridge" from="pedestrian" cap="square"/>
<style-line name="highway:z11" stroke="#fcba5a" width="1.8" blur="0.9"/>
<!-- <style-line name="highway:z11:bridge" from="highway:z11" cap="butt" /> -->
<style-line name="trunk_link" stroke="#fee16e" width="1.3" cap="butt" blur="0.9"/>
<style-line name="trunk" stroke="#fedb52" width="1.6" blur="0.9"/>
<style-line name="primary:z11" stroke="#f2df6d" width="1.5" blur="0.9"/>
<style-line name="secondary:z11" from="primary:z11" width="-0.1"/>
<style-line name="tertiary" from="residential" width="0.2" fade="11"/>
<style-line name="construction" stroke="#e0e0e0" width="1.2" />
<style-line name="highway-service" from="residential" width="-0.6" />
<!-- track|footway|path|cycleway -->
<style-line name="footway" stroke="#c1bcb6" width="1.2" cap="butt" fixed="true"/>
<style-line name="footway:z16" from="footway" width="-1.0" fixed="false" fade="-1"/>
<style-line name="footway:z17" stroke="#faf8f5" width="0.3"/>
<!-- de: ein Weg der für Reiter vorgeshen ist.. -->
<style-line name="bridleway" stroke="#d3cb98" width="0.4" cap="butt"/>
<style-line name="steps" stroke="#f1f0f4" width="0.25" cap="butt" />
<style-line name="water:outline" stroke="#a4bbcc" width="1.0" cap="butt" />
<style-line name="water" stroke="#cca4bbcc" width="0.6" cap="butt" />
<style-area name="water" fill="#001223" />
<!-- no-go area boundary -->
<style-line name="fence" stroke="#444444" width="1.2" fixed="true" cap="butt"/>
<style-line name="aeroway:runway" stroke="#008888" width="1.8" cap="butt" blur="0.7" />
<style-line name="building" stroke="#dd999999" width="1.8" fixed="true" cap="butt"/>
<style-area name="building" fill="#ee202020" fade="15"/>
<!-- ways -->
<rule e="way" k="*" v="*" >
<rule e="way" k="natural" v="grassland|scrub" zoom-min="10">
<use-area name="greens"/>
</rule>
<!-- landuse base -->
<rule e="way" k="landuse" v="*">
<!-- <rule e="way" k="*" zoom-min="10" v="farmland|farm|orchard|vineyard|greenhouse_horticulture|plant_nursery">
<use-area name="farmland"/>
</rule>
<rule e="way" k="*" v="quarry">
<use-area name="quarry"/>
</rule>
<rule e="way" k="*" v="residential|farmyard|retail|commercial|industrial;retail">
<use-area name="residential" />
</rule>
<rule e="way" k="*" v="industrial|railway">
<use-area name ="railway|industrial"/>
</rule>
-->
<!-- <rule e="way" k="*" v="military">
<use-area name="military"/>
</rule> -->
<!--<rule e="way" k="landuse" v="construction|greenfield"> <area fill="#a47c41"
stroke="#e4e4e4" width="0.2" /> </rule> -->
<!-- <rule e="way" k="landuse" v="garages"> <area fill="#d6d6e4" /> </rule> -->
</rule>
<rule e="way" k="landuse|natural|leisure||amenity" v="*">
<!-- kind of more like landuse imho -->
<rule e="way" k="leisure|landuse" v="nature_reserve">
<use-area name="greens2" />
<rule e="way" k="*" v="*" zoom-min="14">
<line stroke="#abe29c" width="1.0" fixed="true" cap="butt" />
</rule>
</rule>
<!-- landuse -->
<rule e="way" k="landuse" v="*" zoom-min="11">
<!-- how about 'leisure' for this one? -->
<rule e="way" k="*" v="cemetery">
<use-area name="park"/>
</rule>
<rule e="way" k="*" v="reservoir|basin">
<use-area name="water" />
</rule>
</rule>
<rule e="way" k="landuse" v="village_green|recreation_ground" >
<use-area name="greens" />
</rule>
<!-- <rule e="way" k="landuse" v="allotments" zoom-min="12">
<use-area name="allotments"/>
</rule>-->
<rule e="way" k="leisure" v="park|common|green|golf_course|dog_park" zoom-min="11">
<use-area name="park"/>
</rule>
<!-- Heideland, keep below forest -->
<rule e="way" k="*" zoom-min="11" v="heath|sand">
<area fill="#0f0f0c" fade="11" />
</rule>
<rule e="way" k="landuse" v="forest">
<use-area name="forest|wood"/>
</rule>
<rule e="way" k="natural" v="wood">
<use-area name="forest|wood"/>
<!-- <line stroke="#abcfab" width="1.5" fixed="true" cap="butt"/> -->
</rule>
<!-- keep grass above forest:wood and leisure:park! -->
<rule e="way" k="landuse" v="grass|meadow">
<use-area name="greens"/>
</rule>
<rule e="way" k="leisure" v="garden">
<use-area name="greens"/>
</rule>
<rule e="way" k="leisure" v="track">
<line stroke="#c1bcb6" width="1.3" cap="butt" fixed="true" />
</rule>
<!-- amenity -->
<rule e="way" k="amenity" v="*">
<rule e="way" k="*" v="kindergarten|school|college|university" zoom-min="14">
<area fill="#cdabde" stroke="#b094bf" stroke-width="0.2" /> </rule>
<rule e="way" k="*" v="parking" zoom-min="14">
<area fill="#f4f4f4" stroke="#d4d4d4" stroke-width="0.2" />
</rule>
<rule e="way" k="*" v="fountain" closed="yes">
<area fill="#b4cbdc" stroke="#000080" stroke-width="0.15" />
</rule>
</rule>
<!-- <rule e="way" k="natural" v="coastline">
<line stroke="#a4bbcc" width="1.2" fixed="true" />
</rule> -->
<!-- natural -->
<rule e="way" k="natural" v="*" zoom-min="10">
<rule e="way" k="*" v="glacier">
<area fill="#fafaff" />
</rule>
<rule e="way" k="*" v="land">
<area fill="#080808" />
</rule>
<!-- <rule e="way" k="*" v="beach">
<area fill="#aaedd400"/>
<line stroke="#fce94f" fixed="true" width="2.8" />
</rule>-->
<rule e="way" k="*" v="marsh|wetland|mud">
<use-area name="greens2" />
</rule>
</rule>
<!-- leisure -->
<rule e="way" k="leisure" v="*" zoom-min="13">
<rule e="way" k="*" v="stadium" >
<area fill="#404040" />
<line stroke="#cccccc" width="1.0" fixed="true" cap="butt" />
</rule>
<!--should be under playing field -->
<!-- <rule e="way" k="*" zoom-min="14" v="sports_centre|water_park">
<area fill="#daefdb" fade="12" />
</rule>
<rule e="way" k="*" zoom-min="15" v="playground|miniature_golf">
<area fill="#f4f4de" />
<line stroke="#fbdbc8" width="0.6" fixed="true" cap="butt" />
</rule>
<rule e="way" k="*" v="playing_fields|pitch">
<area fill="#f4f4de" />
<line stroke="#dbdbc8" width="0.6" fixed="true" cap="butt" />
</rule>
-->
<rule e="way" k="*" v="swimming_pool">
<area fill="#b4cbdc" stroke="#6060ff" width="0.2" />
</rule>
<!-- <rule e="way" k="*" v="track"> <rule e="way" k="area" v="yes|true">
<area fill="#c9d8a2" stroke="#b7c690" width="0.025" /> </rule> <rule
e="way" k="area" v="~|no|false"> <line stroke="#b7c690" width="0.75"
/> </rule> </rule> -->
</rule>
<!-- area outlines need to be above to avoid uggly pixelation where
not aliased polygon overlaps the lines... -->
<rule e="way" k="leisure|landuse" v="*" zoom-min="14">
<rule e="way" k="*" v="nature_reserve">
<line stroke="#abe29c" width="1.0" fixed="true" cap="butt" />
</rule>
<rule e="way" k="*" v="military">
<use-line name="fence" />
</rule>
</rule>
</rule>
<!-- waterways -->
<rule e="way" k="waterway" v="*">
<rule e="way" k="waterway" v="ditch|drain" zoom-min="14">
<use-line name="water" width="0.1" fixed="true"/>
</rule>
<rule e="way" k="waterway" v="canal">
<use-line name="water" width="-0.2"/>
</rule>
<rule e="way" k="waterway" v="stream" zoom-min="14">
<use-line name="water" width="-0.1"/>
</rule>
<style-outline name="river" width="1.0" stroke="#456799" blur="1.0"/>
<rule e="way" k="waterway" v="river" closed="no">
<rule e="way" k="*" v="*" zoom-min="12">
<use-line name="water" width="0.5"/>
<use-outline name="river"/>
</rule>
<rule e="way" k="*" v="*" zoom-max="12">
<use-line name="water" width="1.0" fixed="true" fade="9"/>
</rule>
</rule>
<rule e="way" k="waterway" v="riverbank|dock">
<use-area name="water"/>
<use-line name="water" width="1.0" fixed="true"/>
</rule>
<rule e="way" k="waterway" v="river" closed="yes">
<use-area name="water"/>
<use-line name="water" width="1.0" fixed="true"/>
</rule>
<rule e="way" k="waterway" v="weir">
<line stroke="#000044" width="0.375" cap="butt" />
</rule>
<rule e="way" k="waterway" v="dam" zoom-min="12">
<!-- sehr seltsam was in deutschland so als Damm gekenzeichnet wird.. -->
<line stroke="#ababab" width="1.2" cap="butt" fixed="true" />
</rule>
<rule e="way" k="lock" v="yes|true">
<line stroke="#f8f8f8" width="1.5" cap="butt" />
</rule>
</rule>
<rule e="way" k="natural" v="water">
<use-area name="water"/>
<use-line name="water:outline" width="0.5" fixed="true"/>
</rule>
<!-- sport -->
<!-- <rule e="way" k="sport" v="*"> <rule e="way" k="sport" v="soccer"
zoom-min="17"> <rule e="way" k="sport" v="swimming|canoe|diving|scuba_diving">
<area fill="#b4cbdc" stroke="#6060ff" width="0.2" /> </rule> <rule
e="way" k="sport" v="tennis"> <area fill="#d18a6a" stroke="#b36c4c" width="0.2"
/> </rule> </rule> -->
<!-- tourism areas -->
<rule e="way" k="tourism" v="*">
<!-- <rule e="way" k="tourism" v="attraction"> <area fill="#f2caea" /> </rule> -->
<rule e="way" k="tourism" v="zoo|picnic_site|caravan_site|camp_site">
<area fill="#d7e6b0" />
</rule>
</rule>
<!-- outline 0 -->
<style-outline name="0" stroke="#44000000" width="0.1" />
<!-- tunnel -->
<rule e="way" k="tunnel" v="yes|true" zoom-min="11">
<!-- highway tunnels -->
<rule e="way" k="highway" v="*">
<rule e="way" k="*" v="*" zoom-min="15">
<rule e="way" k="*" v="steps">
<use-line name="steps"/>
<use-outline name="0"/>
</rule>
<rule e="way" k="*" v="track|footway|path|cycleway" zoom-min="16">
<use-line name="footway:z16"/>
</rule>
</rule>
<rule e="way" k="*" v="*" zoom-min="14">
<rule e="way" k="*" v="track|footway|path|cycleway" zoom-max="15">
<use-line name="footway"/>
</rule>
<rule e="way" k="*" v="bridleway">
<use-line name="bridleway"/>
</rule>
<rule e="way" k="*" v="construction">
<use-line name="construction"/>
<use-outline name="0"/>
</rule>
<rule e="way" k="*" v="service">
<rule e="way" k="service" v="-|parking_aisle">
<use-line name="highway-service"/>
<use-outline name="0"/>
</rule>
</rule>
</rule>
<rule e="way" k="*" v="trunk_link|motorway_link">
<use-line name="trunk_link"/>
<use-outline name="0"/>
<use-text name="major-road"/>
</rule>
<rule e="way" k="*" v="*" zoom-min="13">
<rule e="way" k="*" v="byway|pedestrian">
<use-line name="pedestrian"/>
<use-outline name="0"/>
<use-text name="road"/>
</rule>
<rule e="way" k="*" v="residential|road|unclassified|living_street">
<use-line name="residential"/>
<use-outline name="0"/>
<use-text name="road"/>
</rule>
</rule>
<rule e="way" k="*" v="tertiary|secondary_link">
<use-line name="tertiary"/>
<use-outline name="0"/>
<use-text name="road"/>
</rule>
<rule e="way" k="*" v="secondary|primary_link">
<use-line name="secondary:z11"/>
<use-outline name="0"/>
<use-text name="major-road"/>
</rule>
<rule e="way" k="*" v="primary">
<use-line name="primary:z11"/>
<use-outline name="0"/>
<use-text name="major-road"/>
</rule>
<rule e="way" k="*" v="trunk">
<use-line name="trunk" blur="0.3"/>
<use-outline name="0"/>
<!-- <use-outline name="glow"/> -->
<use-text name="major-road"/>
</rule>
<rule e="way" k="*" v="motorway">
<use-line name="highway:z11" blur="0.3"/>
<use-outline name="0"/>
<!-- <use-outline name="glow"/> -->
<use-text name="major-road"/>
</rule>
</rule>
<!-- railway tunnel -->
<rule e="way" k="railway" v="*">
<!-- <rule e="way" k="railway" v="tram|subway|light_rail|narrow_gauge">
<line stroke="#a0a0a0" width="0.8" cap="butt" fixed="true"/>
</rule> -->
<rule e="way" k="railway" v="rail">
<line stroke="#aaaaaa" width="0.9" cap="butt" fixed="true" />
</rule>
</rule>
</rule> <!-- end tunnel -->
<!-- platform cores -->
<rule e="way" k="highway|railway|public_transport" v="platform">
<rule e="way" k="*" v="*" closed="yes">
<area fill="#999999" />
</rule>
<rule e="way" k="*" v="*" closed="no">
<line stroke="#cccccc" width="0.3" />
</rule>
</rule>
<!-- runways areas -->
<rule e="way" k="aeroway" v="*">
<!-- <rule e="way" k="*" v="aerodrome" closed="yes">
<area fill="#050008" />
</rule>
<rule e="way" k="*" v="apron">
<area fill="#050008" />
</rule>-->
<!-- Airport passenger building -->
<rule e="way" k="*" v="terminal|hangar">
<use-area name="building" />
<use-line name="building" />
</rule>
</rule>
<!-- turning circles -->
<!-- <rule e="node" k="highway" v="turning_circle"> <circle r="1.5" scale-radius="true"
fill="#707070" />
</rule> -->
<!-- building -->
<rule e="way" k="building" v="*">
<rule e="way" k="*" v="*" zoom-min="15">
<use-area name="building" fade="15"/>
<use-line name="building" fade="15"/>
<!-- <line stroke="#c9c3c1" width="1.0" fixed="true" cap="butt" fade="15"/>
<area fill="#e9e6e3" fade="15" /> -->
</rule>
<!-- <rule e="way" k="*" v="*" zoom-min="17">
<caption k="name" font-style="bold" font-size="10" fill="#4040ff"
stroke="#ffffff" stroke-width="2.0" />
<caption k="addr:housenumber" font-style="bold" font-size="10" fill="#606060"
stroke="#ffffff" stroke-width="2.0" />
</rule> -->
</rule>
<!-- outline 1 - 4 -->
<style-outline name="glow3" stroke="#ddffffff" width="0.8" blur="0.5" fade="13"/>
<!-- > <style-outline name="glow" stroke="#ee909090" width="0.8" blur="0.5" fade="14"/>-->
<style-outline name="glow2" width="1.0" stroke="#ffffff" blur="1.0" fade="13"/>
<style-outline name="1" stroke="#dd000000" width="-0.3" fade="14"/>
<!-- <style-outline name="1" stroke="#404030"/> -->
<style-outline name="2" stroke="#c0c0c0" />
<style-outline name="primary" stroke="#7f7700" width="0.025"/>
<style-outline name="motorway" stroke="#805f2e" width="0.025"/>
<!-- highway -->
<rule e="way" k="highway" v="*">
<rule e="way" k="*" v="*" zoom-min="5" zoom-max="10">
<rule e="way" k="area" v="~|no|false">
<rule e="way" k="*" v="secondary|primary_link" zoom-min="9">
<line stroke="#ddf2df6d" width="1.8" cap="butt" fixed="true" fade="9"/>
</rule>
<rule e="way" k="*" v="trunk_link|motorway_link" zoom-min="8">
<line stroke="#ddfed6a3" width="1.8" cap="butt" fixed="true" fade="8"/>
</rule>
<rule e="way" k="*" v="primary" zoom-min="5">
<line stroke="#ddf2df6d" cap="butt" fixed="true" width="1.8" fade="5"/> <!-- stroke="#f2df6d" width="1.8" cap="butt" fixed="true" fade="5"/>-->
</rule>
<rule e="way" k="*" v="trunk" zoom-min="5">
<line stroke="#ddfed6a3" width="2.0" cap="butt" fixed="true" fade="5"/>
</rule>
<rule e="way" k="*" v="motorway">
<line stroke="#ddeec693" width="2.2" cap="butt" fixed="true" fade="5"/>
</rule>
</rule>
</rule>
<rule e="way" k="*" v="*" zoom-min="11">
<rule e="way" k="tunnel|bridge" v="~|no|false">
<!-- highway area -->
<rule e="way" k="area" v="yes|true">
<rule e="way" k="*" v="footway" zoom-min="15">
<area fill="#44ffffff" />
<line stroke="#888888" width="0.15" cap="butt" />
</rule>
<rule e="way" k="*" zoom-min="13" v="pedestrian|unclassified|residential|road|living_street">
<area fill="#44ffffff" />
<line stroke="#888888" width="1.0" fixed="true" cap="butt" />
</rule>
<!-- <rule e="way" k="*" v="path" zoom-min="14">
<area fill="#d0d0d0" />
</rule>-->
</rule>
<rule e="way" k="area" v="~|no|false">
<rule e="way" k="*" v="*" zoom-min="15">
<rule e="way" k="*" v="steps">
<use-line name="steps"/>
<use-outline name="2"/>
</rule>
<rule e="way" k="*" v="track|footway|path|cycleway" zoom-min="16" zoom-max="16">
<use-line name="footway:z16"/>
</rule>
<rule e="way" k="*" v="track|footway|path|cycleway" zoom-min="17">
<use-line name="footway:z17"/>
<!-- <use-outline name="1"/> -->
</rule>
</rule>
<rule e="way" k="*" v="*" zoom-min="14">
<rule e="way" k="*" v="track|footway|path|cycleway" zoom-max="15">
<use-line name="footway"/>
</rule>
<rule e="way" k="*" v="bridleway">
<use-line name="bridleway"/>
</rule>
<rule e="way" k="*" v="construction">
<use-line name="construction"/>
<use-outline name="1"/>
</rule>
<rule e="way" k="*" v="service">
<rule e="way" k="service" v="-|parking_aisle">
<use-line name="highway-service"/>
<use-outline name="1"/>
</rule>
<!-- <rule e="way" k="service" v="parking_aisle" zoom-min="16">
<use-line name="highway-service" width="-0.4"/>
<use-outline name="1"/>
</rule> -->
</rule>
</rule>
<rule e="way" k="*" v="trunk_link|motorway_link">
<use-line name="trunk_link"/>
<use-outline name="motorway"/>
<use-text name="major-road"/>
</rule>
<rule e="way" k="*" v="*" zoom-min="13">
<rule e="way" k="*" v="byway|pedestrian">
<use-line name="residential" width="-0.4"/>
<use-outline name="1"/>
<use-text name="road"/>
</rule>
<rule e="way" k="*" v="residential|road|unclassified|living_street">
<use-line name="residential"/>
<use-outline name="1"/>
<use-outline name="glow"/>
<use-text name="road"/>
</rule>
</rule>
<rule e="way" k="*" v="tertiary|secondary_link">
<use-line name="tertiary"/>
<use-outline name="1"/>
<use-outline name="glow"/>
<use-text name="road"/>
</rule>
<rule e="way" k="*" v="secondary|primary_link">
<!-- <line stroke="#fff939" width="1.6" /> -->
<use-line name="secondary:z11"/>
<use-outline name="primary"/>
<use-text name="major-road"/>
</rule>
<rule e="way" k="*" v="primary">
<use-line name="primary:z11"/>
<use-outline name="primary"/>
<use-text name="major-road"/>
</rule>
<rule e="way" k="*" v="trunk">
<use-line name="trunk"/>
<use-outline name="motorway"/>
<use-text name="major-road"/>
</rule>
<rule e="way" k="*" v="motorway">
<use-line name="highway:z11"/>
<use-outline name="motorway"/>
<use-text name="major-road"/>
</rule>
</rule> <!-- end area=~|no|false -->
</rule> <!-- end tunnel|bridge=~|no|false -->
<rule e="way" k="bridge" v="yes|true|viaduct|suspension">
<rule e="way" k="area" v="~|no|false">
<style-outline name="bridge" stroke="#aa202020" width="0.08"/>
<rule e="way" k="*" v="*" zoom-min="15">
<rule e="way" k="*" v="steps">
<use-line name="steps"/>
<use-outline name="bridge"/>
</rule>
<rule e="way" k="*" v="track|footway|path|cycleway" zoom-min="16" zoom-max="16">
<use-line name="footway:z16"/>
</rule>
<rule e="way" k="*" v="track|footway|path|cycleway" zoom-min="17">
<use-line name="footway:z17" cap="butt"/>
<use-outline name="bridge"/>
</rule>
</rule>
<rule e="way" k="*" v="*" zoom-min="14">
<rule e="way" k="*" v="track|footway|path|cycleway" zoom-max="15">
<use-line name="footway"/>
</rule>
<rule e="way" k="*" v="bridleway">
<use-line name="bridleway"/>
</rule>
<rule e="way" k="*" v="construction">
<use-line name="construction" cap="square"/>
<use-outline name="bridge"/>
</rule>
<rule e="way" k="*" v="service">
<use-line name="highway-service" cap="square"/>
<use-outline name="bridge"/>
</rule>
</rule>
<rule e="way" k="*" v="*" zoom-min="13">
<rule e="way" k="*" v="byway|pedestrian">
<use-line name="pedestrian:bridge"/>
<use-outline name="bridge"/>
<use-text name="road"/>
</rule>
<rule e="way" k="*" v="residential|road|unclassified|living_street">
<use-line name="residential:bridge"/>
<use-outline name="bridge"/>
<use-text name="road"/>
</rule>
</rule>
<rule e="way" k="*" v="tertiary|secondary_link">
<use-line name="tertiary" cap="square"/>
<use-outline name="bridge"/>
<use-text name="road"/>
</rule>
<rule e="way" k="*" v="trunk_link|motorway_link">
<use-line name="trunk_link" cap="square"/>
<use-outline name="bridge"/>
<use-text name="major-road"/>
</rule>
<rule e="way" k="*" v="secondary|primary_link">
<!-- <line stroke="#fff939" width="1.6" cap="butt" /> -->
<use-line name="secondary:z11" cap="square"/>
<use-outline name="bridge"/>
<use-text name="major-road"/>
</rule>
<rule e="way" k="*" v="primary">
<use-line name="primary:z11" cap="square"/>
<use-outline name="bridge"/>
<use-text name="major-road"/>
</rule>
<rule e="way" k="*" v="trunk">
<use-line name="trunk" cap="square"/>
<use-outline name="bridge"/>
<use-text name="major-road"/>
</rule>
<rule e="way" k="*" v="motorway">
<use-line name="highway:z11" cap="square"/>
<use-outline name="bridge"/>
<use-text name="major-road"/>
</rule>
</rule> <!-- end area=~|no|false -->
<rule e="way" k="area" v="yes|true">
<rule e="way" k="*" v="footway" zoom-min="15">
<area fill="#fefefe" />
<line stroke="#c0c0c0" width="0.15" cap="butt" />
</rule>
<rule e="way" k="*" zoom-min="13" v="pedestrian|service|unclassified|residential|road|living_street">
<area fill="#ffffff" />
<line stroke="#d0d0d0" width="1.0" fixed="true" cap="butt" />
</rule>
<!-- <rule e="way" k="*" v="path" zoom-min="14">
<area fill="#d0d0d0" />
</rule>-->
</rule> <!-- end area=yes|true -->
</rule> <!-- end bridge=yes -->
</rule> <!-- end zoom-min=11 -->
</rule> <!-- end highway -->
<!-- runways cores -->
<rule e="way" k="aeroway" v="*">
<rule e="way" k="*" v="runway">
<use-line name="aeroway:runway"/>
</rule>
<rule e="way" k="*" v="taxiway">
<use-line name="aeroway:runway" width="-0.8"/>
</rule>
</rule>
<!-- man_made features -->
<!-- <rule e="way" k="man_made" v="pier">
<rule e="way" k="*" v="*" closed="no">
<line stroke="#d0d0d0" width="0.4" cap="butt" />
<line stroke="#e4e4e4" width="0.3" cap="butt" />
</rule>
<rule e="way" k="*" v="*" closed="yes">
<area fill="#e4e4e4" stroke="#d0d0d0" stroke-width="0.05" />
</rule>
</rule> -->
<!-- barriers -->
<rule e="way" k="barrier" v="*">
<!-- <rule e="way" k="*" v="fence|wall|city_wall" zoom-min="15"> <line
stroke="#909090" width="0.1" cap="butt" /> </rule> -->
<rule e="way" k="*" v="retaining_wall" zoom-min="15">
<line stroke="#888888" width="0.1" cap="butt" />
</rule>
</rule>
<!-- non-physical routes -->
<!-- <rule e="way" k="route" v="ferry"> <line stroke="#707070" width="0.3"
stroke-dasharray="15,10" cap="butt" /> </rule> -->
<!-- aerial ways -->
<!-- <rule e="way" k="aerialway" v="*"> <line stroke="#202020" width="0.4"
cap="butt" /> <rule e="way" k="aerialway" v="cable_car"> <lineSymbol
src="jar:/org/mapsforge/android/maps/rendertheme/osmarender/symbols/cable_car.png"
/> </rule> <rule e="way" k="aerialway" v="chair_lift"> <lineSymbol src="jar:/org/mapsforge/android/maps/rendertheme/osmarender/symbols/chair_lift_2.png"
/> </rule> <rule e="way" k="aerialway" v="gondola"> <lineSymbol src="jar:/org/mapsforge/android/maps/rendertheme/osmarender/symbols/gondola.png"
/> </rule> <rule e="way" k="*" v="*" zoom-min="14"> <pathText k="name" font-style="bold"
font-size="10" fill="#606060" stroke="#ffffff" width="2.0" /> </rule>
</rule> -->
<!-- railway (no tunnel) -->
<rule e="way" k="railway" v="*" zoom-min="12">
<rule e="way" k="tunnel" v="~|false|no">
<rule e="way" k="railway" v="station">
<area fill="#aa000000" />
<line stroke="#cccccc" width="1.0" fixed="true"/>
</rule>
<!-- railway bridge casings -->
<rule e="way" k="*" v="*" zoom-min="14">
<rule e="way" k="bridge" v="yes|true">
<rule e="way" k="railway" v="tram">
<line stroke="#777777" width="0.9" cap="butt"
fixed="true" />
</rule>
<rule e="way" k="railway" v="subway|light_rail|narrow_gauge">
<line stroke="#777777" width="0.9" cap="butt"
fixed="true" />
</rule>
<rule e="way" k="railway" v="rail">
<line stroke="#777777" width="0.9" cap="butt"
fixed="true" />
</rule>
</rule>
</rule>
<!-- railway casings and cores -->
<rule e="way" k="railway" v="tram" zoom-min="15">
<line stroke="#887766" width="1.0" fixed="true" />
</rule>
<rule e="way" k="railway" v="light_rail|subway|narrow_gauge" zoom-min="14">
<line stroke="#a0a0a0" width="0.9" cap="butt" fixed="true" />
</rule>
<rule e="way" k="railway" v="rail|turntable" >
<line stroke="#aaaaaa" width="1.0" cap="butt" fixed="true" fade="12"/>
</rule>
<!-- <rule e="way" k="railway" v="rail" zoom-max="14" zoom-min="13">
<line stroke="#8888aa" width="0.6" cap="butt"
fixed="true" />
</rule> -->
<!-- <rule e="way" k="railway" v="rail" zoom-max="13" zoom-min="11">
<line stroke="#bbbbcc" width="0.8" cap="butt" fixed="true" />
</rule> -->
<!-- whatever railway:spur means ... -->
<rule e="way" k="railway" v="disused|spur|abandoned|preserved" >
<line stroke="#cccccc" width="0.8" cap="butt" fixed="true" fade="12"/>
</rule>
</rule>
</rule>
<!-- non-physical boundaries -->
<!-- <rule e="way" k="boundary" v="*"> <rule e="way" k="boundary" v="national_park">
<line stroke="#4ef94b" width="0.25" stroke-dasharray="15, 5, 5, 5"
/> -->
<!--<rule e="way" k="boundary" v="administrative"> -->
<rule e="way" k="admin_level" v="*">
<!-- <rule e="way" k="admin_level" v="11"> <line stroke="#f9574b" width="0.1"
fixed="true" cap="butt" /> </rule> <rule e="way" k="admin_level"
v="10"> <line stroke="#f9574b" width="0.1" fixed="true" cap="butt"
/> </rule> <rule e="way" k="admin_level" v="9"> <line stroke="#f9574b" width="0.1"
fixed="true" cap="butt" /> </rule> <rule e="way" k="admin_level"
v="8"> <line stroke="#f9574b" width="0.3" fixed="true" cap="butt"
/> </rule> <rule e="way" k="admin_level" v="7"> <line stroke="#f9574b" width="0.1"
fixed="true" cap="butt" /> </rule> <rule e="way" k="admin_level"
v="6"> <line stroke="#f9574b" width="0.15" fixed="true" cap="butt"
/> </rule> <rule e="way" k="admin_level" v="5"> <line stroke="#f9574b" width="0.15"
fixed="true" cap="butt" /> </rule> -->
<rule e="way" k="admin_level" v="4">
<line stroke="#8f80dd" width="0.9" fixed="true" cap="butt" />
</rule>
<rule e="way" k="admin_level" v="3">
<line stroke="#0000ff" width="1.0" fixed="true" cap="butt" />
</rule>
<rule e="way" k="admin_level" v="2">
<line stroke="#dddddd" width="1.0" fixed="true" cap="butt" blur="0.3"/>
</rule>
<rule e="way" k="admin_level" v="1">
<line stroke="#ff0000" width="0.95" fixed="true" cap="butt" />
</rule>
</rule>
<!-- </rule> -->
<!-- historic -->
<!-- <rule e="way" k="historic" v="ruins" zoom-min="17">
<caption k="name" font-style="bold" font-size="10" fill="#4040ff" stroke="#ffffff" stroke-width="2.0" />
</rule> -->
<!-- place -->
<rule e="way" k="place" v="locality" zoom-min="17">
<caption k="name" font-style="bold" font-size="10" fill="#000000" stroke="#ffffff" stroke-width="2.0" />
</rule>
<rule e="way" k="debug" v="area">
<line stroke="#ff0000" width="1.2" fixed="true" cap="butt" />
<area fill="#880000ff"/>
<caption k="name" font-size="15" fill="#ff0000" stroke="#444444" stroke-width="2.0"/>
</rule>
<rule e="way" k="debug" v="way">
<line stroke="#00ffff" width="1.5" fixed="true" cap="butt" />
<caption k="name" font-size="15" fill="#00ffff" stroke="#444444" stroke-width="2.0"/>
</rule>
<rule e="way" k="debug" v="box">
<line stroke="#dedeae" width="1.5" fixed="true" cap="butt" />
</rule>
</rule>
<rule e="node" k="*" v="*">
<!-- barrier -->
<rule e="node" k="barrier" v="bollard">
<circle r="1.5" fill="#909090" />
</rule>
<rule e="node" k="debug" v="*" >
<caption k="name" font-size="16" fill="#fefece"/>
</rule>
<!-- highway -->
<!-- <rule e="node" k="highway" v="*"> <rule e="node" k="highway" v="turning_circle">
<circle r="1.4" scale-radius="true" fill="#ffffff" /> </rule> </rule> -->
<!-- historic -->
<!-- <rule e="node" k="historic" v="*"> <circle r="3" fill="#4040ff" stroke="#606060"
width="1.5" /> <rule e="node" k="*" v="*" zoom-min="17"> <caption
k="name" dy="-10" font-style="bold" font-size="10" fill="#4040ff" stroke="#ffffff"
width="2.0" /> </rule> </rule> -->
<!-- house numbers -->
<!-- <rule e="node" k="addr:housenumber" v="*" zoom-min="18"> <caption
k="addr:housenumber" font-style="bold" font-size="10" fill="#606060" stroke="#ffffff"
width="2.0" /> </rule> -->
<!-- place -->
<rule e="node" k="place" v="*">
<rule e="node" k="*" v="suburb|town|village">
<caption k="name" font-size="20" fill="#eeeeee"
stroke="#000020" stroke-width="4.0" />
</rule>
<rule e="node" k="*" v="island" zoom-min="10">
<caption k="name" font-style="bold" font-size="20" fill="#ffffff"
stroke="#ffffff" stroke-width="1.0" />
</rule>
<rule e="node" k="*" v="city">
<caption k="name" font-style="bold" font-size="22" fill="#ffffff"
stroke="#002020" stroke-width="4.0" />
</rule>
<rule e="node" k="*" v="country">
<caption k="name" font-size="22" fill="#ffffff"
stroke="#000000" stroke-width="2.0" />
</rule>
</rule>
<!-- railway -->
<rule e="node" k="railway" v="*">
<rule e="node" k="*" v="station" zoom-min="14">
<circle r="6" fill="#ec2d2d" stroke="#606060" width="1.5" />
<!-- <caption k="name" dy="-10" font-style="bold" font-size="13" fill="#ec2d2d"
stroke="#ffffff" stroke-width="2.0" /> -->
</rule>
<rule e="node" k="*" v="halt|tram_stop" zoom-min="17">
<circle r="4" fill="#ec2d2d" stroke="#606060" width="1.5" />
<!-- <caption k="name" dy="-15" font-style="bold" font-size="11" fill="#ec2d2d"
stroke="#ffffff" stroke-width="2.0" /> -->
</rule>
</rule>
</rule>
</rendertheme>

View File

@ -36,7 +36,7 @@ public class GLMapTile extends MapTile {
* @param zoomLevel
* ..
*/
public GLMapTile(long tileX, long tileY, byte zoomLevel) {
public GLMapTile(int tileX, int tileY, byte zoomLevel) {
super(tileX, tileY, zoomLevel);
mScale = 1;
mTextureID = -1;

View File

@ -17,8 +17,10 @@ package org.mapsforge.android.swrenderer;
import java.util.ArrayList;
import java.util.List;
import org.mapsforge.android.DebugSettings;
import org.mapsforge.android.MapView;
import org.mapsforge.android.mapgenerator.IMapGenerator;
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.mapgenerator.MapTile;
import org.mapsforge.android.rendertheme.IRenderCallback;
import org.mapsforge.android.rendertheme.RenderTheme;
import org.mapsforge.android.rendertheme.renderinstruction.Area;
@ -98,11 +100,16 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
// private long _renderTime;
private int _nodes, _nodesDropped;
private MapView mMapView;
/**
* Constructs a new DatabaseRenderer.
*
* @param mapView
* the MapView
*/
public MapGenerator() {
public MapGenerator(MapView mapView) {
mMapView = mapView;
mCanvasRasterer = new CanvasRasterer();
mLabelPlacement = new LabelPlacement();
@ -131,13 +138,13 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
}
@Override
public boolean executeJob(MapGeneratorJob mapGeneratorJob) {
public boolean executeJob(MapTile mapTile) {
long time_load = System.currentTimeMillis();
_nodes = 0;
_nodesDropped = 0;
// _renderTime = 0;
mCurrentTile = mapGeneratorJob.tile;
mCurrentTile = mapTile;
mCurrentTileZoom = ((long) Tile.TILE_SIZE << mCurrentTile.zoomLevel);
mCurrentTileX = mCurrentTile.pixelX;
mCurrentTileY = mCurrentTile.pixelY;
@ -151,7 +158,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
//
// mTileWidth = mLon2 - mLon1;
// mTileHeight = mLat1 - mLat2;
mScale = mapGeneratorJob.getScale();
// mScale = mapGeneratorJob.getScale();
// Theme theme = mapGeneratorJob.jobParameters.theme;
// if (!theme.equals(mPreviousJobTheme)) {
@ -203,18 +210,20 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
mCanvasRasterer.drawNodes(mAreaLabels);
time_draw = System.currentTimeMillis() - time_draw;
if (mapGeneratorJob.debugSettings.mDrawTileFrames) {
DebugSettings debugSettings = mMapView.getDebugSettings();
if (debugSettings.mDrawTileFrames) {
mCanvasRasterer.drawTileFrame();
}
if (mapGeneratorJob.debugSettings.mDrawTileCoordinates) {
if (debugSettings.mDrawTileCoordinates) {
mCanvasRasterer.drawTileCoordinates(mCurrentTile, time_load, time_draw,
_nodes, _nodesDropped);
}
clearLists();
mapGeneratorJob.setBitmap(mTileBitmap);
// mapGeneratorJob.setBitmap(mTileBitmap);
return true;
}
@ -411,8 +420,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
// mPrevLayer = layer;
}
private List<ShapeContainer> mCurLevelContainer1;
private List<ShapeContainer> mCurLevelContainer2;
// private List<ShapeContainer> mCurLevelContainer1;
// private List<ShapeContainer> mCurLevelContainer2;
@Override
public void renderWay(Line line, int level) {

View File

@ -21,17 +21,13 @@ import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import org.mapsforge.android.DebugSettings;
import org.mapsforge.android.MapView;
import org.mapsforge.android.mapgenerator.IMapGenerator;
import org.mapsforge.android.mapgenerator.JobParameters;
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.mapgenerator.TileCacheKey;
import org.mapsforge.android.mapgenerator.MapTile;
import org.mapsforge.android.mapgenerator.TileDistanceSort;
import org.mapsforge.android.rendertheme.RenderTheme;
import org.mapsforge.android.utils.GlUtils;
@ -40,7 +36,6 @@ import org.mapsforge.core.MercatorProjection;
import org.mapsforge.core.Tile;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.opengl.Matrix;
/**
@ -65,11 +60,11 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private double mDrawX, mDrawY;
private long mTileX, mTileY;
private float mMapScale;
private DebugSettings mDebugSettings;
private JobParameters mJobParameter;
// private DebugSettings mDebugSettings;
// private JobParameters mJobParameter;
private MapPosition mMapPosition, mPrevMapPosition;
private ArrayList<MapGeneratorJob> mJobList;
private ArrayList<MapTile> mJobList;
ArrayList<Integer> mTextures;
MapView mMapView;
@ -78,8 +73,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
GLMapTile[] newTiles;
int currentTileCnt = 0;
private TileCacheKey mTileCacheKey;
private LinkedHashMap<TileCacheKey, GLMapTile> mTiles;
// private TileCacheKey mTileCacheKey;
// private LinkedHashMap<TileCacheKey, GLMapTile> mTiles;
private ArrayList<GLMapTile> mTileList;
private boolean processedTile = true;
@ -96,7 +91,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
*/
public MapRenderer(MapView mapView) {
mMapView = mapView;
mDebugSettings = mapView.getDebugSettings();
// mDebugSettings = mapView.getDebugSettings();
mMapScale = 1;
float[] vertices = {
@ -110,12 +105,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mVertices.put(vertices);
mTextures = new ArrayList<Integer>();
mJobList = new ArrayList<MapGeneratorJob>();
mJobList = new ArrayList<MapTile>();
mTiles = new LinkedHashMap<TileCacheKey, GLMapTile>(100);
// mTiles = new LinkedHashMap<TileCacheKey, GLMapTile>(100);
mTileList = new ArrayList<GLMapTile>();
mTileCacheKey = new TileCacheKey();
// mTileCacheKey = new TileCacheKey();
mInitial = true;
}
@ -144,8 +139,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
for (int j = mTileList.size() - 1, cnt = 0; cnt < remove; j--, cnt++) {
GLMapTile t = mTileList.remove(j);
mTileCacheKey.set(t.tileX, t.tileY, t.zoomLevel);
mTiles.remove(mTileCacheKey);
// mTileCacheKey.set(t.tileX, t.tileY, t.zoomLevel);
// mTiles.remove(mTileCacheKey);
for (int i = 0; i < 4; i++) {
if (t.child[i] != null)
@ -176,63 +171,63 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
long pixelLeft = x - offsetX;
long pixelTop = y - offsetY;
long tileLeft = MercatorProjection.pixelXToTileX(pixelLeft, zoomLevel);
long tileTop = MercatorProjection.pixelYToTileY(pixelTop, zoomLevel);
long tileRight = MercatorProjection.pixelXToTileX(pixelRight, zoomLevel);
long tileBottom = MercatorProjection.pixelYToTileY(pixelBottom, zoomLevel);
int tileLeft = MercatorProjection.pixelXToTileX(pixelLeft, zoomLevel);
int tileTop = MercatorProjection.pixelYToTileY(pixelTop, zoomLevel);
int tileRight = MercatorProjection.pixelXToTileX(pixelRight, zoomLevel);
int tileBottom = MercatorProjection.pixelYToTileY(pixelBottom, zoomLevel);
mJobList.clear();
// IMapGenerator mapGenerator = mMapView.getMapGenerator();
int tiles = 0;
for (long tileY = tileTop - 1; tileY <= tileBottom + 1; tileY++) {
for (long tileX = tileLeft - 1; tileX <= tileRight + 1; tileX++) {
for (int tileY = tileTop - 1; tileY <= tileBottom + 1; tileY++) {
for (int tileX = tileLeft - 1; tileX <= tileRight + 1; tileX++) {
GLMapTile tile = mTiles.get(mTileCacheKey.set(tileX, tileY, zoomLevel));
// GLMapTile tile = mTiles.get(mTileCacheKey.set(tileX, tileY, zoomLevel));
//
// if (tile == null) {
// tile = new GLMapTile(tileX, tileY, zoomLevel);
// TileCacheKey key = new TileCacheKey(mTileCacheKey);
// mTiles.put(key, tile);
//
// mTileCacheKey.set((tileX >> 1), (tileY >> 1), (byte) (zoomLevel - 1));
// tile.parent = mTiles.get(mTileCacheKey);
//
// long xx = tileX << 1;
// long yy = tileY << 1;
// byte z = (byte) (zoomLevel + 1);
//
// tile.child[0] = mTiles.get(mTileCacheKey.set(xx, yy, z));
// tile.child[1] = mTiles.get(mTileCacheKey.set(xx + 1, yy, z));
// tile.child[2] = mTiles.get(mTileCacheKey.set(xx, yy + 1, z));
// tile.child[3] = mTiles.get(mTileCacheKey.set(xx + 1, yy + 1, z));
//
// mTileList.add(tile);
// }
if (tile == null) {
tile = new GLMapTile(tileX, tileY, zoomLevel);
TileCacheKey key = new TileCacheKey(mTileCacheKey);
mTiles.put(key, tile);
mTileCacheKey.set((tileX >> 1), (tileY >> 1), (byte) (zoomLevel - 1));
tile.parent = mTiles.get(mTileCacheKey);
long xx = tileX << 1;
long yy = tileY << 1;
byte z = (byte) (zoomLevel + 1);
tile.child[0] = mTiles.get(mTileCacheKey.set(xx, yy, z));
tile.child[1] = mTiles.get(mTileCacheKey.set(xx + 1, yy, z));
tile.child[2] = mTiles.get(mTileCacheKey.set(xx, yy + 1, z));
tile.child[3] = mTiles.get(mTileCacheKey.set(xx + 1, yy + 1, z));
mTileList.add(tile);
}
newTiles[tiles++] = tile;
if (!tile.isReady || (tile.getScale() != scale)) {
// tile.isLoading = true;
// approximation for TileScheduler
if (tileY < tileTop || tileY > tileBottom || tileX < tileLeft
|| tileX > tileRight)
tile.isVisible = false;
else
tile.isVisible = true;
MapGeneratorJob job = new MapGeneratorJob(tile, mJobParameter,
mDebugSettings);
job.setScale(scale);
mJobList.add(job);
}
// newTiles[tiles++] = tile;
//
// if (!tile.isReady || (tile.getScale() != scale)) {
// // tile.isLoading = true;
// // approximation for TileScheduler
// if (tileY < tileTop || tileY > tileBottom || tileX < tileLeft
// || tileX > tileRight)
// tile.isVisible = false;
// else
// tile.isVisible = true;
//
// MapGeneratorJob job = new MapGeneratorJob(tile, mJobParameter,
// mDebugSettings);
// job.setScale(scale);
// mJobList.add(job);
// }
}
}
synchronized (this) {
limitCache(zoomLevel, (mTiles.size() - 200));
limitCache(zoomLevel, (mTileList.size() - 200));
for (int i = 0; i < tiles; i++)
currentTiles[i] = newTiles[i];
@ -243,9 +238,9 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mMapScale = scale;
}
if (mJobList.size() > 0) {
mMapView.addJobs(mJobList);
}
// if (mJobList.size() > 0) {
// mMapView.addJobs(mJobList);
// }
return true;
}
@ -260,12 +255,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mMapPosition = mMapView.getMapPosition().getMapPosition();
long x = (long) MercatorProjection.longitudeToPixelX(
mMapPosition.geoPoint.getLongitude(),
mMapPosition.zoomLevel);
long y = (long) MercatorProjection
.latitudeToPixelY(mMapPosition.geoPoint.getLatitude(),
mMapPosition.zoomLevel);
long x = (long) MercatorProjection.longitudeToPixelX(mMapPosition);
long y = (long) MercatorProjection.latitudeToPixelY(mMapPosition);
long tileX = MercatorProjection.pixelXToTileX(x, mMapPosition.zoomLevel);
long tileY = MercatorProjection.pixelYToTileY(y, mMapPosition.zoomLevel);
@ -304,12 +295,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mMapView.requestRender();
}
private MapGeneratorJob mMapGeneratorJob = null;
// private MapGeneratorJob mMapGeneratorJob = null;
@Override
public boolean passTile(MapGeneratorJob mapGeneratorJob) {
public boolean passTile(MapTile mapTile) {
mMapGeneratorJob = mapGeneratorJob;
// mMapGeneratorJob = mapGeneratorJob;
processedTile = false;
mMapView.requestRender();
@ -344,11 +335,11 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} else {
z = 1.0f / (1 << -diff);
}
drawX = MercatorProjection
.longitudeToPixelX(mMapPosition.geoPoint.getLongitude(),
tile.zoomLevel);
drawY = MercatorProjection
.latitudeToPixelY(mMapPosition.geoPoint.getLatitude(), tile.zoomLevel);
// drawX = MercatorProjection
// .longitudeToPixelX(mMapPosition.geoPoint.getLongitude(),
// tile.zoomLevel);
// drawY = MercatorProjection
// .latitudeToPixelY(mMapPosition.geoPoint.getLatitude(), tile.zoomLevel);
}
@ -430,71 +421,71 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
// lock position and currentTiles while drawing
synchronized (this) {
if (mMapGeneratorJob != null) {
tile = (GLMapTile) mMapGeneratorJob.tile;
// TODO tile bitmaps texture to smaller parts avoiding uploading full
// bitmap when not necessary
if (tile.getTexture() >= 0) {
// reuse tile texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tile.getTexture());
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
mMapGeneratorJob.getBitmap());
} else if (mTextures.size() > 0) {
// reuse texture from previous tiles
Integer texture;
texture = mTextures.remove(mTextures.size() - 1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture.intValue());
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
mMapGeneratorJob.getBitmap());
tile.setTexture(texture.intValue());
} else {
// create texture
tile.setTexture(GlUtils.loadTextures(mMapGeneratorJob.getBitmap()));
}
tile.setScale(mMapGeneratorJob.getScale());
tile.isReady = true;
tile.isLoading = false;
mMapGeneratorJob = null;
processedTile = true;
// loadedTexture = true;
}
int tileSize = (int) (Tile.TILE_SIZE * mMapScale);
int hWidth = mWidth >> 1;
int hHeight = mHeight >> 1;
for (int i = 0, n = currentTileCnt; i < n; i++) {
tile = currentTiles[i];
float x = (float) (tile.pixelX - mDrawX);
float y = (float) (tile.pixelY - mDrawY);
// clip rendering to tile boundaries
GLES20.glScissor(
hWidth + (int) (x * mMapScale) - 2,
hHeight - (int) (y * mMapScale) - tileSize - 2,
tileSize + 4, tileSize + 4);
if (drawTile(tile, 0, 0.0f))
continue;
// or two zoom level above
for (int k = 0; k < 4; k++) {
if (((child = tile.child[k]) != null)) {
if (drawTile(child, 2, 0.1f))
continue;
for (int j = 0; j < 4; j++)
if ((child2 = child.child[j]) != null)
drawTile(child2, 2, 0.1f);
}
}
}
}
// synchronized (this) {
// if (mMapGeneratorJob != null) {
//
// tile = (GLMapTile) mMapGeneratorJob.tile;
// // TODO tile bitmaps texture to smaller parts avoiding uploading full
// // bitmap when not necessary
// if (tile.getTexture() >= 0) {
// // reuse tile texture
// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tile.getTexture());
// GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
// mMapGeneratorJob.getBitmap());
// } else if (mTextures.size() > 0) {
// // reuse texture from previous tiles
// Integer texture;
// texture = mTextures.remove(mTextures.size() - 1);
//
// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture.intValue());
// GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
// mMapGeneratorJob.getBitmap());
// tile.setTexture(texture.intValue());
// } else {
// // create texture
// tile.setTexture(GlUtils.loadTextures(mMapGeneratorJob.getBitmap()));
// }
//
// tile.setScale(mMapGeneratorJob.getScale());
// tile.isReady = true;
// tile.isLoading = false;
//
// mMapGeneratorJob = null;
// processedTile = true;
// // loadedTexture = true;
// }
// int tileSize = (int) (Tile.TILE_SIZE * mMapScale);
// int hWidth = mWidth >> 1;
// int hHeight = mHeight >> 1;
// for (int i = 0, n = currentTileCnt; i < n; i++) {
// tile = currentTiles[i];
//
// float x = (float) (tile.pixelX - mDrawX);
// float y = (float) (tile.pixelY - mDrawY);
//
// // clip rendering to tile boundaries
// GLES20.glScissor(
// hWidth + (int) (x * mMapScale) - 2,
// hHeight - (int) (y * mMapScale) - tileSize - 2,
// tileSize + 4, tileSize + 4);
//
// if (drawTile(tile, 0, 0.0f))
// continue;
//
// // or two zoom level above
// for (int k = 0; k < 4; k++) {
// if (((child = tile.child[k]) != null)) {
//
// if (drawTile(child, 2, 0.1f))
// continue;
//
// for (int j = 0; j < 4; j++)
// if ((child2 = child.child[j]) != null)
// drawTile(child2, 2, 0.1f);
// }
// }
// }
// }
}
@Override
@ -508,10 +499,10 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
GLES20.glViewport(0, 0, width, height);
mDebugSettings = mMapView.getDebugSettings();
mJobParameter = mMapView.getJobParameters();
// mDebugSettings = mMapView.getDebugSettings();
// mJobParameter = mMapView.getJobParameters();
mTiles.clear();
// mTiles.clear();
mTileList.clear();
mTextures.clear();
mInitial = true;
@ -581,7 +572,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
@Override
public IMapGenerator createMapGenerator() {
return new MapGenerator();
return new MapGenerator(mMapView);
}
@Override

View File

@ -23,6 +23,7 @@ import org.mapsforge.database.MapFileInfo;
import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
@ -43,7 +44,6 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.EditText;
@ -51,14 +51,14 @@ import android.widget.SeekBar;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
/**
* A map application which uses the features from the mapsforge map library. The map can be centered to the current
* location. A simple file browser for selecting the map file is also included. Some preferences can be adjusted via the
* {@link EditPreferences} activity.
*/
public class TileMap extends MapActivity { // implements ActionBar.OnNavigationListener {
public class TileMap extends MapActivity {
// implements ActionBar.OnNavigationListener {
private static final String BUNDLE_CENTER_AT_FIRST_FIX = "centerAtFirstFix";
private static final String BUNDLE_SHOW_MY_LOCATION = "showMyLocation";
private static final String BUNDLE_SNAP_TO_LOCATION = "snapToLocation";
@ -76,7 +76,7 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
private MyLocationListener mMyLocationListener;
private boolean mShowMyLocation;
private boolean mSnapToLocation;
private ToggleButton mSnapToLocationView;
// private ToggleButton mSnapToLocationView;
private WakeLock mWakeLock;
MapController mMapController;
MapView mMapView;
@ -86,12 +86,12 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
getMenuInflater().inflate(R.menu.options_menu, menu);
else
getMenuInflater().inflate(R.menu.options_menu_pre_honeycomb, menu);
mMenu = menu;
return true;
}
@ -99,9 +99,9 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// case R.id.menu_info_map_file:
// showDialog(DIALOG_INFO_MAP_FILE);
// return true;
case R.id.menu_info_about:
startActivity(new Intent(this, InfoView.class));
return true;
case R.id.menu_position:
return true;
@ -161,6 +161,10 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
mMapView.setRenderTheme(InternalRenderTheme.OSMARENDER);
return true;
case R.id.menu_render_theme_tronrender:
mMapView.setRenderTheme(InternalRenderTheme.TRONRENDER);
return true;
case R.id.menu_render_theme_select_file:
startRenderThemePicker();
return true;
@ -176,6 +180,10 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
onCreateOptionsMenu(menu);
Log.d("TileMap", "prepare options...");
// menu.findItem(R.id.menu_info_map_file).setEnabled(true);
@ -193,9 +201,15 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
menu.findItem(R.id.menu_position_map_center).setEnabled(true);
menu.findItem(R.id.menu_render_theme).setEnabled(true);
menu.findItem(R.id.menu_mapfile).setEnabled(true);
// menu.findItem(R.id.menu_mapfile).setEnabled(true);
return true;
if (mMapDatabase == MapDatabases.MAP_READER)
menu.findItem(R.id.menu_mapfile).setVisible(true);
else
menu.findItem(R.id.menu_mapfile).setVisible(false);
return super.onPrepareOptionsMenu(menu);
// return true;
}
@Override
@ -227,7 +241,7 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
mMyLocationListener.setCenterAtFirstFix(centerAtFirstFix);
mLocationManager.requestLocationUpdates(bestProvider, 1000, 0,
mMyLocationListener);
mSnapToLocationView.setVisibility(View.VISIBLE);
// mSnapToLocationView.setVisibility(View.VISIBLE);
return true;
}
return false;
@ -323,17 +337,18 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
mMapView = (MapView) findViewById(R.id.mapView);
configureMapView();
mSnapToLocationView = (ToggleButton) findViewById(R.id.snapToLocationView);
mSnapToLocationView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (isSnapToLocationEnabled()) {
disableSnapToLocation(true);
} else {
enableSnapToLocation(true);
}
}
});
// mSnapToLocationView = (ToggleButton) findViewById(R.id.snapToLocationView);
//
// mSnapToLocationView.setOnClickListener(new OnClickListener() {
// @Override
// public void onClick(View view) {
// if (isSnapToLocationEnabled()) {
// disableSnapToLocation(true);
// } else {
// enableSnapToLocation(true);
// }
// }
// });
// get the pointers to different system services
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
@ -404,7 +419,7 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
builder.setPositiveButton(R.string.ok, null);
return builder.create();
} else {
// do dialog will be created
// no dialog will be created
return null;
}
}
@ -533,40 +548,31 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
if (preferences.contains("mapDatabase")) {
String name = preferences.getString("mapDatabase",
MapDatabases.POSTGIS_READER.name());
MapDatabases.PBMAP_READER.name());
MapDatabases mapDatabaseNew;
try {
mapDatabaseNew = MapDatabases.valueOf(name);
} catch (IllegalArgumentException e) {
mapDatabaseNew = MapDatabases.POSTGIS_READER;
mapDatabaseNew = MapDatabases.PBMAP_READER;
}
// mapDatabaseInternalNew = MapDatabaseInternal.PBMAP_READER;
Log.d("VectorTileMap", "set map database " + mapDatabaseNew);
if (mapDatabaseNew != mMapDatabase) {
mMapView.setMapDatabase(mapDatabaseNew);
mMapDatabase = mapDatabaseNew;
}
// if (mapDatabaseNew != mMapDatabase) {
// IMapDatabase mapDatabase = MapDatabaseFactory
// .createMapDatabase(mapDatabaseNew);
//
// mMapView.setMapDatabase(mapDatabase);
// mMapDatabase = mapDatabaseNew;
// }
}
try {
String textScaleDefault = getString(R.string.preferences_text_scale_default);
mMapView.setTextScale(Float.parseFloat(preferences.getString("textScale",
textScaleDefault)));
} catch (NumberFormatException e) {
mMapView.setTextScale(1);
}
// try {
// String textScaleDefault = getString(R.string.preferences_text_scale_default);
// mMapView.setTextScale(Float.parseFloat(preferences.getString("textScale",
// textScaleDefault)));
// } catch (NumberFormatException e) {
// mMapView.setTextScale(1);
// }
if (preferences.getBoolean("fullscreen", false)) {
Log.i("mapviewer", "FULLSCREEN");
@ -601,6 +607,18 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
} else {
mMapView.setMapFile(mMapView.getMapFile());
}
if (Build.VERSION.SDK_INT >= 11) {
VersionHelper.refreshActionBarMenu(this);
}
}
static class VersionHelper {
@TargetApi(11)
static void refreshActionBarMenu(Activity activity) {
activity.invalidateOptionsMenu();
}
}
@Override
@ -628,7 +646,7 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
// circleOverlay = null;
// itemizedOverlay = null;
// }
mSnapToLocationView.setVisibility(View.GONE);
// mSnapToLocationView.setVisibility(View.GONE);
return true;
}
return false;
@ -643,7 +661,7 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
void disableSnapToLocation(boolean showToast) {
if (mSnapToLocation) {
mSnapToLocation = false;
mSnapToLocationView.setChecked(false);
// mSnapToLocationView.setChecked(false);
mMapView.setClickable(true);
if (showToast) {
showToastOnUiThread(getString(R.string.snap_to_location_disabled));

View File

@ -22,12 +22,14 @@ import java.util.Comparator;
import org.mapsforge.app.R;
import org.mapsforge.app.filefilter.ValidFileFilter;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
@ -223,13 +225,16 @@ public class FilePicker extends Activity implements AdapterView.OnItemClickListe
editor.commit();
}
@TargetApi(11)
@Override
protected void onResume() {
super.onResume();
// getActionBar().hide();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
getActionBar().hide();
// check if the full screen mode should be activated
// if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fullscreen", false)) {
// if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fullscreen",
// false)) {
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
// getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
// } else {

View File

@ -16,6 +16,8 @@ package org.mapsforge.app.preferences;
import org.mapsforge.app.R;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceActivity;
@ -29,10 +31,13 @@ public class EditPreferences extends PreferenceActivity {
addPreferencesFromResource(R.xml.preferences);
}
@TargetApi(11)
@Override
protected void onResume() {
super.onResume();
// getActionBar().hide();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
getActionBar().hide();
// check if the full screen mode should be activated
// if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fullscreen",

View File

@ -14,21 +14,16 @@
*/
package org.mapsforge.core;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
/**
* A GeoPoint represents an immutable pair of latitude and longitude coordinates.
*/
public class GeoPoint implements Comparable<GeoPoint>, Serializable {
public class GeoPoint implements Comparable<GeoPoint> {
/**
* Conversion factor from degrees to microdegrees.
*/
private static final double CONVERSION_FACTOR = 1000000d;
private static final long serialVersionUID = 1L;
/**
* The latitude value of this GeoPoint in microdegrees (degrees * 10^6).
*/
@ -42,7 +37,7 @@ public class GeoPoint implements Comparable<GeoPoint>, Serializable {
/**
* The hash code of this object.
*/
private transient int hashCodeValue;
private int hashCodeValue = 0;
/**
* @param latitude
@ -57,7 +52,6 @@ public class GeoPoint implements Comparable<GeoPoint>, Serializable {
double limitLongitude = MercatorProjection.limitLongitude(longitude);
this.longitudeE6 = (int) (limitLongitude * CONVERSION_FACTOR);
this.hashCodeValue = calculateHashCode();
}
/**
@ -116,6 +110,9 @@ public class GeoPoint implements Comparable<GeoPoint>, Serializable {
@Override
public int hashCode() {
if (this.hashCodeValue == 0)
this.hashCodeValue = calculateHashCode();
return this.hashCodeValue;
}
@ -139,9 +136,4 @@ public class GeoPoint implements Comparable<GeoPoint>, Serializable {
result = 31 * result + this.longitudeE6;
return result;
}
private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
objectInputStream.defaultReadObject();
this.hashCodeValue = calculateHashCode();
}
}

View File

@ -14,20 +14,17 @@
*/
package org.mapsforge.core;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
/**
* A MapPosition represents an immutable pair of {@link GeoPoint} and zoom level.
*/
public class MapPosition implements Serializable {
private static final long serialVersionUID = 1L;
public class MapPosition {
/**
* The map position.
*/
public final GeoPoint geoPoint;
// public final GeoPoint geoPoint;
public final double lon;
public final double lat;
/**
* The zoom level.
@ -38,10 +35,11 @@ public class MapPosition implements Serializable {
* 1.0 - 2.0 scale of current zoomlevel
*/
public final float scale;
/**
* The hash code of this object.
*/
private transient int hashCodeValue;
public final float angle;
public final double x;
public final double y;
/**
* @param geoPoint
@ -51,62 +49,40 @@ public class MapPosition implements Serializable {
* @param scale
* ...
*/
public MapPosition(GeoPoint geoPoint, byte zoomLevel, float scale) {
this.geoPoint = geoPoint;
// this.geoPoint = geoPoint;
this.zoomLevel = zoomLevel;
this.scale = scale;
this.hashCodeValue = calculateHashCode();
this.lat = geoPoint.getLatitude();
this.lon = geoPoint.getLongitude();
this.angle = 0;
this.x = MercatorProjection.longitudeToPixelX(this.lon, zoomLevel);
this.y = MercatorProjection.latitudeToPixelY(this.lat, zoomLevel);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (!(obj instanceof MapPosition)) {
return false;
}
MapPosition other = (MapPosition) obj;
if (this.geoPoint == null) {
if (other.geoPoint != null) {
return false;
}
} else if (!this.geoPoint.equals(other.geoPoint)) {
return false;
}
if (this.zoomLevel != other.zoomLevel) {
return false;
}
return true;
}
@Override
public int hashCode() {
return this.hashCodeValue;
public MapPosition(double latitude, double longitude, byte zoomLevel, float scale,
float angle) {
this.zoomLevel = zoomLevel;
this.scale = scale;
this.lat = latitude;
this.lon = longitude;
this.angle = angle;
this.x = MercatorProjection.longitudeToPixelX(longitude, zoomLevel);
this.y = MercatorProjection.latitudeToPixelY(latitude, zoomLevel);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("MapPosition [geoPoint=");
builder.append(this.geoPoint);
builder.append("lat");
builder.append(this.lat);
builder.append("lon");
builder.append(this.lon);
builder.append(", zoomLevel=");
builder.append(this.zoomLevel);
builder.append("]");
return builder.toString();
}
/**
* @return the hash code of this object.
*/
private int calculateHashCode() {
int result = 7;
result = 31 * result + ((this.geoPoint == null) ? 0 : this.geoPoint.hashCode());
result = 31 * result + this.zoomLevel;
return result;
}
private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
objectInputStream.defaultReadObject();
this.hashCodeValue = calculateHashCode();
}
}

View File

@ -53,7 +53,8 @@ public final class MercatorProjection {
* @return the ground resolution at the given latitude and zoom level.
*/
public static double calculateGroundResolution(double latitude, byte zoomLevel) {
return Math.cos(latitude * (Math.PI / 180)) * EARTH_CIRCUMFERENCE / ((long) Tile.TILE_SIZE << zoomLevel);
return Math.cos(latitude * (Math.PI / 180)) * EARTH_CIRCUMFERENCE
/ ((long) Tile.TILE_SIZE << zoomLevel);
}
/**
@ -71,6 +72,12 @@ public final class MercatorProjection {
* ((long) Tile.TILE_SIZE << zoomLevel);
}
public static double latitudeToPixelY(MapPosition mapPosition) {
double sinLatitude = Math.sin(mapPosition.lat * (Math.PI / 180));
return (0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI))
* ((long) Tile.TILE_SIZE << mapPosition.zoomLevel);
}
/**
* Converts a latitude coordinate (in degrees) to a tile Y number at a certain zoom level.
*
@ -102,6 +109,16 @@ public final class MercatorProjection {
return Math.max(Math.min(longitude, LONGITUDE_MAX), LONGITUDE_MIN);
}
public static double wrapLongitude(double longitude) {
if (longitude < -180)
return Math.max(Math.min(360 + longitude, LONGITUDE_MAX), LONGITUDE_MIN);
else if (longitude > 180)
return Math.max(Math.min(longitude - 360, LONGITUDE_MAX), LONGITUDE_MIN);
return longitude;
}
/**
* Converts a longitude coordinate (in degrees) to a pixel X coordinate at a certain zoom level.
*
@ -115,6 +132,11 @@ public final class MercatorProjection {
return (longitude + 180) / 360 * ((long) Tile.TILE_SIZE << zoomLevel);
}
public static double longitudeToPixelX(MapPosition mapPosition) {
return (mapPosition.lon + 180) / 360
* ((long) Tile.TILE_SIZE << mapPosition.zoomLevel);
}
/**
* Converts a longitude coordinate (in degrees) to the tile X number at a certain zoom level.
*
@ -150,8 +172,9 @@ public final class MercatorProjection {
* the zoom level at which the coordinate should be converted.
* @return the tile X number.
*/
public static long pixelXToTileX(double pixelX, byte zoomLevel) {
return (long) Math.min(Math.max(pixelX / Tile.TILE_SIZE, 0), Math.pow(2, zoomLevel) - 1);
public static int pixelXToTileX(double pixelX, byte zoomLevel) {
return (int) Math.min(Math.max(pixelX / Tile.TILE_SIZE, 0),
Math.pow(2, zoomLevel) - 1);
}
/**
@ -177,8 +200,9 @@ public final class MercatorProjection {
* the zoom level at which the coordinate should be converted.
* @return the tile Y number.
*/
public static long pixelYToTileY(double pixelY, byte zoomLevel) {
return (long) Math.min(Math.max(pixelY / Tile.TILE_SIZE, 0), Math.pow(2, zoomLevel) - 1);
public static int pixelYToTileY(double pixelY, byte zoomLevel) {
return (int) Math.min(Math.max(pixelY / Tile.TILE_SIZE, 0),
Math.pow(2, zoomLevel) - 1);
}
/**

View File

@ -49,7 +49,7 @@ public class Tag {
*/
public String value;
private transient int hashCodeValue;
private transient int hashCodeValue = 0;
/**
* @param tag
@ -63,7 +63,6 @@ public class Tag {
}
this.key = tag.substring(0, splitPosition).intern();
this.value = tag.substring(splitPosition + 1).intern();
this.hashCodeValue = calculateHashCode();
}
public Tag(String tag, boolean hashValue) {
@ -76,8 +75,6 @@ public class Tag {
this.value = tag.substring(splitPosition + 1);
else
this.value = tag.substring(splitPosition + 1).intern();
this.hashCodeValue = calculateHashCode();
}
/**
@ -89,7 +86,6 @@ public class Tag {
public Tag(String key, String value) {
this.key = (key == null ? null : key.intern());
this.value = (value == null ? null : value.intern());
this.hashCodeValue = calculateHashCode();
}
/**
@ -109,7 +105,6 @@ public class Tag {
this.key = (key == null ? null : key);
this.value = (value == null ? null : value);
}
this.hashCodeValue = calculateHashCode();
}
@Override
@ -121,14 +116,17 @@ public class Tag {
}
Tag other = (Tag) obj;
if ((this.key != other.key) || (this.value != other.value))
return false;
if ((this.key == other.key) && (this.value == other.value))
return true;
return true;
return false;
}
@Override
public int hashCode() {
if (this.hashCodeValue == 0)
this.hashCodeValue = calculateHashCode();
return this.hashCodeValue;
}

View File

@ -19,38 +19,27 @@ package org.mapsforge.core;
* with their zoom level. The actual area that a tile covers on a map depends on the underlying map projection.
*/
public class Tile {
/**
* Bytes per pixel required in a map tile bitmap.
*/
public static final byte TILE_BYTES_PER_PIXEL = 2;
/**
* Width and height of a map tile in pixel.
*/
public static int TILE_SIZE = 256;
/**
* Size of a single uncompressed map tile bitmap in bytes.
*/
public static final int TILE_SIZE_IN_BYTES = TILE_SIZE * TILE_SIZE
* TILE_BYTES_PER_PIXEL;
/**
* The X number of this tile.
*/
public final long tileX;
public final int tileX;
/**
* The Y number of this tile.
*/
public final long tileY;
public final int tileY;
/**
* The Zoom level of this tile.
*/
public final byte zoomLevel;
private transient int hashCodeValue;
/**
* the pixel X coordinate of the upper left corner of this tile.
*/
@ -70,51 +59,12 @@ public class Tile {
* @param zoomLevel
* the zoom level of the tile.
*/
public Tile(long tileX, long tileY, byte zoomLevel) {
public Tile(int tileX, int tileY, byte zoomLevel) {
this.tileX = tileX;
this.tileY = tileY;
this.pixelX = this.tileX * TILE_SIZE;
this.pixelY = this.tileY * TILE_SIZE;
this.zoomLevel = zoomLevel;
this.hashCodeValue = calculateHashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (!(obj instanceof Tile)) {
return false;
}
Tile other = (Tile) obj;
if (this.tileX != other.tileX) {
return false;
} else if (this.tileY != other.tileY) {
return false;
} else if (this.zoomLevel != other.zoomLevel) {
return false;
}
return true;
}
/**
* @return the pixel X coordinate of the upper left corner of this tile.
*/
// public long getPixelX() {
// return this.pixelX;
// }
/**
* @return the pixel Y coordinate of the upper left corner of this tile.
*/
// public long getPixelY() {
// return this.pixelY;
// }
@Override
public int hashCode() {
return this.hashCodeValue;
}
@Override
@ -130,14 +80,34 @@ public class Tile {
return stringBuilder.toString();
}
/**
* @return the hash code of this object.
*/
private int calculateHashCode() {
int result = 7;
result = 31 * result + (int) (this.tileX ^ (this.tileX >>> 32));
result = 31 * result + (int) (this.tileY ^ (this.tileY >>> 32));
result = 31 * result + this.zoomLevel;
return result;
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof Tile))
return false;
Tile o = (Tile) obj;
if (o.tileX == this.tileX && o.tileY == this.tileY
&& o.zoomLevel == this.zoomLevel)
return true;
return false;
}
private int mHash = 0;
@Override
public int hashCode() {
if (mHash == 0) {
int result = 7;
result = 31 * result + this.tileX;
result = 31 * result + this.tileY;
result = 31 * result + this.zoomLevel;
mHash = result;
}
return mHash;
}
}

View File

@ -15,10 +15,14 @@
package org.mapsforge.database.pbmap;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
@ -46,6 +50,7 @@ import org.mapsforge.database.IMapDatabaseCallback;
import org.mapsforge.database.MapFileInfo;
import org.mapsforge.database.QueryResult;
import android.os.Environment;
import android.util.Log;
/**
@ -62,6 +67,11 @@ public class MapDatabase implements IMapDatabase {
private boolean mOpenFile = false;
private static final boolean USE_CACHE = false;
private static final String CACHE_DIRECTORY = "/Android/data/org.mapsforge.app/cache/";
private static final String CACHE_FILE = "%d-%d-%d.tile";
// private static final String URL = "http://city.informatik.uni-bremen.de:8020/test/%d/%d/%d.osmtile";
private static final String URL = "http://city.informatik.uni-bremen.de/osmstache/test/%d/%d/%d.osmtile";
// private static final String URL = "http://city.informatik.uni-bremen.de/osmstache/gis2/%d/%d/%d.osmtile";
@ -69,6 +79,7 @@ public class MapDatabase implements IMapDatabase {
// new BasicHeader("Accept-Encoding", "gzip");
private static final int MAX_TAGS_CACHE = 100;
private static Map<String, Tag> tagHash = Collections
.synchronizedMap(new LinkedHashMap<String, Tag>(
MAX_TAGS_CACHE, 0.75f, true) {
@ -79,8 +90,6 @@ public class MapDatabase implements IMapDatabase {
protected boolean removeEldestEntry(Entry<String, Tag> e) {
if (size() < MAX_TAGS_CACHE)
return false;
// Log.d(TAG, "cache: drop " + e.getValue());
return true;
}
});
@ -92,30 +101,72 @@ public class MapDatabase implements IMapDatabase {
private int mCurTagCnt;
private HttpClient mClient;
private HttpGet mRequest = null;
private IMapDatabaseCallback mMapGenerator;
private float mScaleFactor;
private HttpGet mRequest = null;
private Tile mTile;
private FileOutputStream mCacheFile;
@Override
public QueryResult executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
mCanceled = false;
// mCanceled = false;
mCacheFile = null;
// just used for debugging ....
mTile = tile;
// Log.d(TAG, "get tile >> : " + tile);
String url = String.format(URL, Integer.valueOf(tile.zoomLevel),
Long.valueOf(tile.tileX), Long.valueOf(tile.tileY));
HttpGet getRequest = new HttpGet(url);
mRequest = getRequest;
mMapGenerator = mapDatabaseCallback;
mCurTagCnt = 0;
mScaleFactor = REF_TILE_SIZE / Tile.TILE_SIZE;
File f;
if (USE_CACHE) {
f = new File(cacheDir, String.format(CACHE_FILE,
Integer.valueOf(tile.zoomLevel),
Long.valueOf(tile.tileX),
Long.valueOf(tile.tileY)));
if (f.exists()) {
FileInputStream in;
Log.d(TAG, "using cache: " + tile);
try {
in = new FileInputStream(f);
decode(in);
in.close();
return QueryResult.SUCCESS;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
String url = String.format(URL,
Integer.valueOf(tile.zoomLevel),
Long.valueOf(tile.tileX),
Long.valueOf(tile.tileY));
HttpGet getRequest = new HttpGet(url);
mRequest = getRequest;
try {
// HttpURLConnection urlConn = (HttpURLConnection) new URL(url).openConnection();
// // urlConn.setUseCaches(false);
//
// InputStream in = urlConn.getInputStream();
// try {
// decode(in);
// } finally {
// urlConn.disconnect();
// }
HttpResponse response = mClient.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
final HttpEntity entity = response.getEntity();
@ -125,10 +176,10 @@ public class MapDatabase implements IMapDatabase {
entity.consumeContent();
return QueryResult.FAILED;
}
if (mTile.isCanceled) {
Log.d(TAG, "1 loading canceled " + mTile);
entity.consumeContent();
return QueryResult.FAILED;
}
@ -136,6 +187,16 @@ public class MapDatabase implements IMapDatabase {
// GZIPInputStream zis = null;
try {
is = entity.getContent();
if (USE_CACHE) {
try {
Log.d(TAG, "writing cache: " + tile);
mCacheFile = new FileOutputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
// zis = new GZIPInputStream(is);
decode(is);
@ -149,15 +210,22 @@ public class MapDatabase implements IMapDatabase {
}
} catch (SocketException ex) {
Log.d(TAG, "Socket exception: " + ex.getMessage());
// f.delete();
return QueryResult.FAILED;
} catch (SocketTimeoutException ex) {
Log.d(TAG, "Socket Timeout exception: " + ex.getMessage());
// f.delete();
return QueryResult.FAILED;
} catch (UnknownHostException ex) {
Log.d(TAG, "no network");
// f.delete();
return QueryResult.FAILED;
} catch (Exception ex) {
getRequest.abort();
// f.delete();
ex.printStackTrace();
return QueryResult.FAILED;
}
mRequest = null;
if (mTile.isCanceled) {
@ -165,11 +233,21 @@ public class MapDatabase implements IMapDatabase {
return QueryResult.FAILED;
}
// Log.d(TAG, "get tile << : " + tile);
if (USE_CACHE) {
try {
mCacheFile.flush();
mCacheFile.close();
} catch (IOException e) {
e.printStackTrace();
}
mCacheFile = null;
}
return QueryResult.SUCCESS;
}
private static File cacheDir;
@Override
public String getMapProjection() {
return null;
@ -190,11 +268,14 @@ public class MapDatabase implements IMapDatabase {
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setStaleCheckingEnabled(params, false);
HttpConnectionParams.setConnectionTimeout(params, 10 * 1000);
HttpConnectionParams.setConnectionTimeout(params, 20 * 1000);
HttpConnectionParams.setSoTimeout(params, 60 * 1000);
HttpConnectionParams.setSocketBufferSize(params, 16384);
mClient = new DefaultHttpClient(params);
HttpConnectionParams.setSocketBufferSize(params, 32768);
HttpClientParams.setRedirecting(params, false);
// HttpClientParams.setCookiePolicy(params, CookiePolicy.ACCEPT_NONE);
mClient = new DefaultHttpClient(params);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http",
PlainSocketFactory.getSocketFactory(), 80));
@ -202,16 +283,33 @@ public class MapDatabase implements IMapDatabase {
@Override
public FileOpenResult openFile(File mapFile) {
createClient();
if (USE_CACHE) {
if (cacheDir == null) {
// cacheDir = mapFile;
String externalStorageDirectory = Environment
.getExternalStorageDirectory()
.getAbsolutePath();
String cacheDirectoryPath = externalStorageDirectory + CACHE_DIRECTORY;
cacheDir = createDirectory(cacheDirectoryPath);
Log.d(TAG, "cache dir: " + cacheDir);
}
}
return new FileOpenResult();
}
@Override
public void closeFile() {
mOpenFile = false;
if (mClient != null)
if (mClient != null) {
mClient.getConnectionManager().shutdown();
mClient = null;
}
}
@Override
@ -219,12 +317,31 @@ public class MapDatabase implements IMapDatabase {
return null;
}
private static File createDirectory(String pathName) {
File file = new File(pathName);
if (!file.exists() && !file.mkdirs()) {
throw new IllegalArgumentException("could not create directory: " + file);
} else if (!file.isDirectory()) {
throw new IllegalArgumentException("not a directory: " + file);
} else if (!file.canRead()) {
throw new IllegalArgumentException("cannot read directory: " + file);
} else if (!file.canWrite()) {
throw new IllegalArgumentException("cannot write directory: " + file);
}
return file;
}
// // // hand sewed tile protocol buffers decoder // // //
private static final int BUFFER_SIZE = 65536;
private final byte[] buffer = new byte[BUFFER_SIZE];
// position in read buffer
private int bufferPos;
// bytes available in read buffer
private int bufferSize;
// (bytesRead - bufferPos) + bufferSize
// private int bufferLimit;
// bytes processed
private int bytesRead;
private InputStream inputStream;
@ -256,8 +373,6 @@ public class MapDatabase implements IMapDatabase {
while ((val = decodeVarint32()) > 0) {
// read tag and wire type
int tag = (val >> 3);
// int wireType = (val & 7);
// Log.d(TAG, "tile " + tag + " " + wireType);
switch (tag) {
case TAG_TILE_TAGS:
@ -286,7 +401,13 @@ public class MapDatabase implements IMapDatabase {
private boolean decodeTileTags() throws IOException {
String tagString = decodeString();
// Log.d(TAG, "tag>" + tagString + "<");
if (tagString == null || tagString.length() == 0) {
curTags[mCurTagCnt++] = new Tag(Tag.TAG_KEY_NAME, "...");
return false;
}
Tag tag = tagHash.get(tagString);
if (tag == null) {
@ -298,7 +419,6 @@ public class MapDatabase implements IMapDatabase {
tagHash.put(tagString, tag);
}
// FIXME ...
if (mCurTagCnt >= MAX_TILE_TAGS) {
MAX_TILE_TAGS = mCurTagCnt + 10;
Tag[] tmp = new Tag[MAX_TILE_TAGS];
@ -331,9 +451,6 @@ public class MapDatabase implements IMapDatabase {
break;
int tag = (val >> 3);
// int wireType = val & 7;
// Log.d(TAG, "way " + tag + " " + wireType + " bytes:" + bytes);
int cnt;
switch (tag) {
case TAG_WAY_TAGS:
@ -345,9 +462,9 @@ public class MapDatabase implements IMapDatabase {
break;
case TAG_WAY_COORDS:
cnt = decodeWayCoordinates(skip);
int cnt = decodeWayCoordinates(skip);
if (cnt != coordCnt) {
Log.d(TAG, "EEEK wrong number of coordintes");
Log.d(TAG, "X wrong number of coordintes");
fail = true;
}
break;
@ -369,20 +486,20 @@ public class MapDatabase implements IMapDatabase {
break;
default:
Log.d(TAG, "invalid type for way: " + tag);
Log.d(TAG, "X invalid type for way: " + tag);
}
}
if (fail || index == null || tags == null || indexCnt == 0 || tagCnt == 0) {
Log.d(TAG, "..." + index + " " + (tags != null ? tags[0] : "...") + " "
+ indexCnt + " " + coordCnt + " "
+ tagCnt);
Log.d(TAG, "failed reading way: bytes:" + bytes + " index:" + index + " tag:"
+ (tags != null ? tags[0] : "...") + " "
+ indexCnt + " " + coordCnt + " " + tagCnt);
return false;
}
float[] coords = tmpCoords;
// FIXME !!!!!
// FIXME, remove all tiles from cache then remove this below
if (layer == 0)
layer = 5;
@ -393,8 +510,6 @@ public class MapDatabase implements IMapDatabase {
private boolean decodeTileNodes() throws IOException {
int bytes = decodeVarint32();
// Log.d(TAG, "decode nodes " + bytes);
int end = bytesRead + bytes;
int tagCnt = 0;
int coordCnt = 0;
@ -408,9 +523,6 @@ public class MapDatabase implements IMapDatabase {
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:
@ -418,9 +530,9 @@ public class MapDatabase implements IMapDatabase {
break;
case TAG_NODE_COORDS:
cnt = decodeNodeCoordinates(coordCnt, layer, tags);
int cnt = decodeNodeCoordinates(coordCnt, layer, tags);
if (cnt != coordCnt) {
Log.d(TAG, "EEEK wrong number of coordintes");
Log.d(TAG, "X wrong number of coordintes");
return false;
}
break;
@ -438,7 +550,7 @@ public class MapDatabase implements IMapDatabase {
break;
default:
Log.d(TAG, "invalid type for node: " + tag);
Log.d(TAG, "X invalid type for node: " + tag);
}
}
@ -457,15 +569,13 @@ public class MapDatabase implements IMapDatabase {
int lastX = 0;
int lastY = 0;
while (bufferPos < end && cnt < numNodes) {
int lon = decodeZigZag32(decodeVarint32()); // * mScaleFactor;
int lat = decodeZigZag32(decodeVarint32()); // * mScaleFactor;
int lon = decodeZigZag32(decodeVarint32());
int lat = decodeZigZag32(decodeVarint32());
lastX = lon + lastX;
lastY = lat + lastY;
mMapGenerator.renderPointOfInterest(layer,
lastY / scale,
lastX / scale,
tags);
lastY / scale, lastX / scale, tags);
cnt += 2;
}
return cnt;
@ -500,8 +610,8 @@ public class MapDatabase implements IMapDatabase {
// Log.d(TAG, "variable tag: " + curTags[tagNum]);
tags[cnt++] = curTags[tagNum];
} else {
Log.d(TAG, "NULL TAG: " + mTile + " could find tag:" + tagNum + " "
+ tagCnt + "/" + cnt);
Log.d(TAG, "NULL TAG: " + mTile + " could find tag:"
+ tagNum + " " + tagCnt + "/" + cnt);
}
}
}
@ -573,41 +683,38 @@ public class MapDatabase implements IMapDatabase {
if (buf[pos] >= 0) {
result = buf[pos++];
} else if (buf[pos + 1] >= 0) {
result = buf[pos] & 0x7f
result = (buf[pos] & 0x7f)
| buf[pos + 1] << 7;
pos += 2;
} else if (buf[pos + 2] >= 0) {
result = buf[pos] & 0x7f
| buf[pos + 1] << 7
| buf[pos + 2] << 14;
result = (buf[pos] & 0x7f)
| (buf[pos + 1] & 0x7f) << 7
| (buf[pos + 2]) << 14;
pos += 3;
} else if (buf[pos + 3] >= 0) {
result = buf[pos] & 0x7f
| buf[pos + 1] << 7
| buf[pos + 2] << 14
| buf[pos + 3] << 21;
result = (buf[pos] & 0x7f)
| (buf[pos + 1] & 0x7f) << 7
| (buf[pos + 2] & 0x7f) << 14
| (buf[pos + 3]) << 21;
pos += 4;
Log.d(TAG, "4 Stuffs too large " + mTile);
} else {
result = buf[pos] & 0x7f
| buf[pos + 1] << 7
| buf[pos + 2] << 14
| buf[pos + 3] << 21
| buf[pos + 4] << 28;
pos += 5;
result = (buf[pos] & 0x7f)
| (buf[pos + 1] & 0x7f) << 7
| (buf[pos + 2] & 0x7f) << 14
| (buf[pos + 3] & 0x7f) << 21
| (buf[pos + 4]) << 28;
Log.d(TAG, "5 Stuffs too large " + mTile);
Log.d(TAG, "Stuffs too large " + mTile);
pos += 4;
int i = 0;
while (buf[pos++] < 0 && i < 10)
i++;
if (i == 10)
throw new IOException("X malformed VarInt32");
if (buf[pos + 4] < 0) {
Log.d(TAG, "Stuffs too large ...");
int i = 0;
while (i++ < 5) {
if (buf[pos++] >= 0)
break;
}
if (i == 5)
throw new IOException("EEEK malformed varInt");
}
}
if (even) {
x = ((result >>> 1) ^ -(result & 1));
@ -628,70 +735,120 @@ public class MapDatabase implements IMapDatabase {
return cnt;
}
private void readBuffer() throws IOException {
private int readBuffer(int size) throws IOException {
int read = 0;
int len = inputStream.read(buffer, 0, BUFFER_SIZE);
if (len < 0) {
buffer[bufferPos] = 0;
// Log.d(TAG, " nothing to read... pos " + bufferPos + ", size "
// + bufferSize + ", read " + bytesRead);
return;
}
bufferSize = len;
bufferPos = 0;
}
private void readBuffer(int size) throws IOException {
if (size < (bufferSize - bufferPos))
return;
if (bufferPos + size < bufferSize)
return 0;
if (size > BUFFER_SIZE) {
// FIXME throw exception for now, but frankly better
// sanitize tile data on compilation.
// this only happen with strings or coordinates larger than 64kb
throw new IOException("EEEK requested size too large");
throw new IOException("X requested size too large");
}
if ((size - bufferSize) + bufferPos > BUFFER_SIZE) {
// copy bytes left to read from buffer to the beginning of buffer
System.arraycopy(buffer, bufferPos, buffer, 0, bufferSize - bufferPos);
if (bufferSize == bufferPos) {
bufferPos = 0;
bufferSize = 0;
} else if (bufferPos + (size - bufferSize) > BUFFER_SIZE) {
Log.d(TAG, "wrap buffer" + (size - bufferSize) + " " + bufferPos);
// copy bytes left to read to the beginning of buffer
bufferSize -= bufferPos;
System.arraycopy(buffer, bufferPos, buffer, 0, bufferSize);
bufferPos = 0;
}
while ((bufferSize - bufferPos) < size) {
if (mTile.isCanceled) {
throw new IOException("canceled " + mTile);
}
// read until requested size is available in buffer
int len = inputStream.read(buffer, bufferSize, BUFFER_SIZE - bufferSize);
if (len < 0) {
buffer[bufferSize - 1] = 0; // FIXME is this needed?
// finished reading, mark end
buffer[bufferSize] = 0;
break;
}
read += len;
if (mCacheFile != null)
mCacheFile.write(buffer, bufferSize, len);
bufferSize += len;
if (mCanceled)
throw new IOException("... canceld?");
}
// Log.d(TAG, "needed " + size + " pos " + bufferPos + ", size "
// + bufferSize
// + ", read " + bytesRead);
return read;
}
private boolean mCanceled;
@Override
public void cancel() {
mCanceled = true;
if (mRequest != null) {
mRequest.abort();
mRequest = null;
}
}
private int decodeVarint32() throws IOException {
int pos = bufferPos;
if (pos + 10 > bufferSize) {
readBuffer(8192);
pos = bufferPos;
}
byte[] buf = buffer;
if (buf[pos] >= 0) {
bufferPos += 1;
bytesRead += 1;
return buf[pos];
} else if (buf[pos + 1] >= 0) {
bufferPos += 2;
bytesRead += 2;
return (buf[pos] & 0x7f)
| (buf[pos + 1]) << 7;
} else if (buf[pos + 2] >= 0) {
bufferPos += 3;
bytesRead += 3;
return (buf[pos] & 0x7f)
| (buf[pos + 1] & 0x7f) << 7
| (buf[pos + 2]) << 14;
} else if (buf[pos + 3] >= 0) {
bufferPos += 4;
bytesRead += 4;
return (buf[pos] & 0x7f)
| (buf[pos + 1] & 0x7f) << 7
| (buf[pos + 2] & 0x7f) << 14
| (buf[pos + 3]) << 21;
}
int result = (buf[pos] & 0x7f)
| (buf[pos + 1] & 0x7f) << 7
| (buf[pos + 2] & 0x7f) << 14
| (buf[pos + 3] & 0x7f) << 21
| (buf[pos + 4]) << 28;
Log.d(TAG, "got a big number, eh?");
int read = 5;
pos += 4;
// 'Discard upper 32 bits' - the original comment.
// havent found this in any document but the code provided by google.
// no idea what this is for, just seems fsckin stupid...
while (buf[pos++] < 0 && read < 10)
read++;
if (read == 10)
throw new IOException("X malformed VarInt32");
bufferPos += read;
bytesRead += read;
return result;
}
/* All code below is taken from or based on Google's Protocol Buffers implementation: */
// Protocol Buffers - Google's data interchange format
@ -724,61 +881,21 @@ public class MapDatabase implements IMapDatabase {
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
private byte readRawByte() throws IOException {
if (bufferPos == bufferSize) {
readBuffer();
}
bytesRead++;
return buffer[bufferPos++];
}
private int decodeVarint32() throws IOException {
byte tmp = readRawByte();
if (tmp >= 0) {
return tmp;
}
int result = tmp & 0x7f;
if ((tmp = readRawByte()) >= 0) {
return result | tmp << 7;
}
result |= (tmp & 0x7f) << 7;
if ((tmp = readRawByte()) >= 0) {
return result | tmp << 14;
}
result |= (tmp & 0x7f) << 14;
if ((tmp = readRawByte()) >= 0) {
return result | tmp << 21;
}
result |= (tmp & 0x7f) << 21;
result |= (tmp = readRawByte()) << 28;
if (tmp < 0) {
// Discard upper 32 bits.
for (int i = 0; i < 5; i++) {
if (readRawByte() >= 0) {
return result;
}
}
Log.d(TAG, "EEK malformedVarint");
// FIXME throw some poo
}
return result;
}
private String decodeString() throws IOException {
final int size = decodeVarint32();
readBuffer(size);
final String result = new String(buffer, bufferPos, size, "UTF-8");
// Log.d(TAG, "read string " + read + " " + size + " " + bufferPos + " " + result);
bufferPos += size;
bytesRead += size;
return result;
}
public static int decodeZigZag32(final int n) {
private static int decodeZigZag32(final int n) {
return (n >>> 1) ^ -(n & 1);
}