- 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>
<activity android:name=".preferences.EditPreferences" /> <activity android:name=".preferences.EditPreferences" />
<activity android:name=".filepicker.FilePicker" /> <activity android:name=".filepicker.FilePicker" />
<activity android:name=".InfoView" android:theme="@android:style/Theme.NoTitleBar" />
</application> </application>
</manifest> </manifest>

View File

@ -6,9 +6,10 @@
<meta http-equiv="Content-Style-Type" content="text/css" /> <meta http-equiv="Content-Style-Type" content="text/css" />
</head> </head>
<body style="padding: 0.5em;"> <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 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>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> <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>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> This software is based on <a href="https://code.google.com/p/mapsforge">mapsforge</a> library 0.2.4.</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>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> </body>
</html> </html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

View File

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

View File

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

View File

@ -48,6 +48,9 @@
<!-- <item <!-- <item
android:id="@+id/menu_info_map_file" android:id="@+id/menu_info_map_file"
android:title="@string/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> </menu>
</item> </item>
@ -61,6 +64,9 @@
<item <item
android:id="@+id/menu_render_theme_osmarender" android:id="@+id/menu_render_theme_osmarender"
android:title="@string/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 <item
android:id="@+id/menu_render_theme_select_file" android:id="@+id/menu_render_theme_select_file"
android:title="@string/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"?> <?xml version="1.0" encoding="UTF-8"?>
<resources> <resources>
<string-array name="preferences_map_generator_values"> <!-- <string-array name="preferences_map_generator_values">
<item>Mapfile</item> <item>Mapfile</item>
<item>PostGIS</item> <item>PostGIS</item>
<item>OpenScienceMap</item> <item>OpenScienceMap</item>
</string-array> </string-array> -->
<string-array name="preferences_scale_bar_unit_values"> <string-array name="preferences_scale_bar_unit_values">
<item>angloamerikanisch</item> <item>angloamerikanisch</item>

View File

@ -1,11 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<resources> <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"> <string-array name="preferences_text_scale_values">
<item>hyvin pieni</item> <item>hyvin pieni</item>
<item>pieni</item> <item>pieni</item>

View File

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

View File

@ -1,16 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<resources> <resources>
<string-array name="preferences_map_database_keys"> <string-array name="preferences_map_database_keys">
<item>MAP_READER</item>
<!-- <item>MAP_READER</item> -->
<item>POSTGIS_READER</item> <item>POSTGIS_READER</item>
<item>PBMAP_READER</item> <item>PBMAP_READER</item>
</string-array> </string-array>
<string name="preferences_map_database_default">POSTGIS_READER</string>
<string name="preferences_map_database_default">PBMAP_READER</string>
<string-array name="preferences_scale_bar_unit_keys"> <string-array name="preferences_scale_bar_unit_keys">
<item>imperial</item> <item>imperial</item>
<item>metric</item> <item>metric</item>
</string-array> </string-array>
<string name="preferences_scale_bar_unit_default">metric</string> <string name="preferences_scale_bar_unit_default">metric</string>
<string-array name="preferences_text_scale_keys"> <string-array name="preferences_text_scale_keys">
@ -20,6 +24,7 @@
<item>1.3</item> <item>1.3</item>
<item>1.6</item> <item>1.6</item>
</string-array> </string-array>
<string name="preferences_text_scale_default">1.0</string> <string name="preferences_text_scale_default">1.0</string>
<string-array name="view_sections"> <string-array name="view_sections">
@ -28,4 +33,5 @@
<item>Overlays</item> <item>Overlays</item>
<item>etc</item> <item>etc</item>
</string-array> </string-array>
</resources> </resources>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<resources> <resources>
<string-array name="preferences_map_generator_values"> <string-array name="preferences_map_generator_values">
<item>Mapfile</item> <!-- <item>Mapfile</item> -->
<item>PostGIS</item> <item>PostGIS</item>
<item>OpenScienceMap</item> <item>OpenScienceMap</item>
</string-array> </string-array>
@ -59,6 +59,7 @@
<string name="menu_preferences">Preferences</string> <string name="menu_preferences">Preferences</string>
<string name="menu_render_theme">Render theme</string> <string name="menu_render_theme">Render theme</string>
<string name="menu_render_theme_osmarender">Default 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_render_theme_select_file">Select XML file …</string>
<string name="menu_screenshot">Screenshot</string> <string name="menu_screenshot">Screenshot</string>
<string name="menu_screenshot_jpeg">JPEG (lossy)</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"> <style name="MyActionBar" parent="android:style/Widget.Holo.Light.ActionBar">
<item name="android:background">@drawable/action_bar</item> <item name="android:background">@drawable/action_bar</item>
<item name="android:windowActionBarOverlay">true</item>
</style> </style>
<style name="Theme.TileMap" parent="android:style/Theme.Holo"> <style name="Theme.TileMap" parent="android:style/Theme.Holo">

View File

@ -15,7 +15,7 @@
package org.mapsforge.android; package org.mapsforge.android;
import org.mapsforge.android.mapgenerator.IMapGenerator; 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 org.mapsforge.android.rendertheme.RenderTheme;
import android.opengl.GLSurfaceView; import android.opengl.GLSurfaceView;
@ -26,11 +26,11 @@ import android.opengl.GLSurfaceView;
public interface IMapRenderer extends GLSurfaceView.Renderer { public interface IMapRenderer extends GLSurfaceView.Renderer {
/** /**
* @param mapGeneratorJob * @param tile
* the mapGeneratorJob holding Tile data * the mapGeneratorJob holding Tile data
* @return true if the tile was processed * @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 * @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 // save the map position and zoom level
MapPosition mapPosition = mMapView.getMapPosition().getMapPosition(); MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
if (mapPosition != null) { if (mapPosition != null) {
GeoPoint geoPoint = mapPosition.geoPoint; GeoPoint geoPoint = new GeoPoint(mapPosition.lat, mapPosition.lon);
editor.putInt(KEY_LATITUDE, geoPoint.latitudeE6); editor.putInt(KEY_LATITUDE, geoPoint.latitudeE6);
editor.putInt(KEY_LONGITUDE, geoPoint.longitudeE6); editor.putInt(KEY_LONGITUDE, geoPoint.longitudeE6);
editor.putInt(KEY_ZOOM_LEVEL, mapPosition.zoomLevel); 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 int ONE_MILE = 5280;
private static final Paint SCALE_BAR = new Paint(Paint.ANTI_ALIAS_FLAG); 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 Paint SCALE_BAR_STROKE = new Paint(Paint.ANTI_ALIAS_FLAG);
private static final int[] SCALE_BAR_VALUES_IMPERIAL = { 26400000, 10560000, 5280000, 2640000, 1056000, 528000, private static final int[] SCALE_BAR_VALUES_IMPERIAL = { 26400000, 10560000, 5280000,
264000, 105600, 52800, 26400, 10560, 5280, 2000, 1000, 500, 200, 100, 50, 20, 10, 5, 2, 1 }; 2640000, 1056000, 528000,
private static final int[] SCALE_BAR_VALUES_METRIC = { 10000000, 5000000, 2000000, 1000000, 500000, 200000, 100000, 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 }; 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 = new Paint(Paint.ANTI_ALIAS_FLAG);
private static final Paint SCALE_TEXT_STROKE = 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) { MapScaleBar(MapView mapView) {
mMapView = 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); mMapScaleCanvas = new Canvas(mMapScaleBitmap);
mTextFields = new HashMap<TextField, String>(); mTextFields = new HashMap<TextField, String>();
setDefaultTexts(); setDefaultTexts();
@ -173,8 +177,8 @@ public class MapScaleBar {
return true; return true;
} }
double latitudeDiff = Math.abs(currentMapPosition.geoPoint.getLatitude() double latitudeDiff = Math.abs(currentMapPosition.lat
- mMapPosition.geoPoint.getLatitude()); - mMapPosition.lat);
if (latitudeDiff > LATITUDE_REDRAW_THRESHOLD) { if (latitudeDiff > LATITUDE_REDRAW_THRESHOLD) {
return true; return true;
} }
@ -245,7 +249,8 @@ public class MapScaleBar {
} }
mMapPosition = mMapView.getMapPosition().getMapPosition(); mMapPosition = mMapView.getMapPosition().getMapPosition();
double groundResolution = MercatorProjection.calculateGroundResolution(mMapPosition.geoPoint.getLatitude(), double groundResolution = MercatorProjection.calculateGroundResolution(
mMapPosition.lat,
mMapPosition.zoomLevel); mMapPosition.zoomLevel);
int[] scaleBarValues; int[] scaleBarValues;

View File

@ -24,13 +24,12 @@ import javax.xml.parsers.ParserConfigurationException;
import org.mapsforge.android.input.TouchHandler; import org.mapsforge.android.input.TouchHandler;
import org.mapsforge.android.mapgenerator.IMapGenerator; import org.mapsforge.android.mapgenerator.IMapGenerator;
import org.mapsforge.android.mapgenerator.JobParameters;
import org.mapsforge.android.mapgenerator.JobQueue; import org.mapsforge.android.mapgenerator.JobQueue;
import org.mapsforge.android.mapgenerator.MapDatabaseFactory; import org.mapsforge.android.mapgenerator.MapDatabaseFactory;
import org.mapsforge.android.mapgenerator.MapDatabases; import org.mapsforge.android.mapgenerator.MapDatabases;
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.mapgenerator.MapRendererFactory; import org.mapsforge.android.mapgenerator.MapRendererFactory;
import org.mapsforge.android.mapgenerator.MapRenderers; import org.mapsforge.android.mapgenerator.MapRenderers;
import org.mapsforge.android.mapgenerator.MapTile;
import org.mapsforge.android.mapgenerator.MapWorker; import org.mapsforge.android.mapgenerator.MapWorker;
import org.mapsforge.android.mapgenerator.Theme; import org.mapsforge.android.mapgenerator.Theme;
import org.mapsforge.android.rendertheme.ExternalRenderTheme; 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 static final Byte DEFAULT_START_ZOOM_LEVEL = Byte.valueOf((byte) 16);
private final MapController mMapController; private final MapController mMapController;
// private final MapMover mMapMover;
// private final ZoomAnimator mZoomAnimator;
// private final MapScaleBar mMapScaleBar;
private final MapViewPosition mMapViewPosition; private final MapViewPosition mMapViewPosition;
private final MapZoomControls mMapZoomControls; private final MapZoomControls mMapZoomControls;
@ -95,10 +91,11 @@ public class MapView extends GLSurfaceView {
private JobQueue mJobQueue; private JobQueue mJobQueue;
private MapWorker mMapWorkers[]; private MapWorker mMapWorkers[];
private int mNumMapWorkers = 4; private int mNumMapWorkers = 4;
private JobParameters mJobParameters; private DebugSettings debugSettings;
public DebugSettings debugSettings;
private String mMapFile; private String mMapFile;
private File cacheDir;
/** /**
* @param context * @param context
* the enclosing MapActivity instance. * the enclosing MapActivity instance.
@ -139,30 +136,25 @@ public class MapView extends GLSurfaceView {
// TODO make this dpi dependent // TODO make this dpi dependent
Tile.TILE_SIZE = 400; Tile.TILE_SIZE = 400;
// setWillNotDraw(true);
// setWillNotCacheDrawing(true);
MapActivity mapActivity = (MapActivity) context; MapActivity mapActivity = (MapActivity) context;
cacheDir = context.getFilesDir();
debugSettings = new DebugSettings(false, false, false, false); debugSettings = new DebugSettings(false, false, false, false);
mJobParameters = new JobParameters(DEFAULT_RENDER_THEME, DEFAULT_TEXT_SCALE);
mMapController = new MapController(this); mMapController = new MapController(this);
mMapDatabaseType = mapDatabaseType; mMapDatabaseType = mapDatabaseType;
mMapViewPosition = new MapViewPosition(this); mMapViewPosition = new MapViewPosition(this);
// mMapScaleBar = new MapScaleBar(this);
mMapZoomControls = new MapZoomControls(mapActivity, this); mMapZoomControls = new MapZoomControls(mapActivity, this);
mProjection = new MapViewProjection(this); mProjection = new MapViewProjection(this);
mTouchEventHandler = new TouchHandler(mapActivity, this); mTouchEventHandler = new TouchHandler(mapActivity, this);
mJobQueue = new JobQueue(this); mJobQueue = new JobQueue();
// mMapMover = new MapMover(this);
// mMapMover.start();
// mZoomAnimator = new ZoomAnimator(this);
// mZoomAnimator.start();
mMapRenderer = MapRendererFactory.createMapRenderer(this, mapGeneratorType); mMapRenderer = MapRendererFactory.createMapRenderer(this, mapGeneratorType);
mMapWorkers = new MapWorker[mNumMapWorkers]; mMapWorkers = new MapWorker[mNumMapWorkers];
@ -172,7 +164,6 @@ public class MapView extends GLSurfaceView {
if (mDebugDatabase) { if (mDebugDatabase) {
mapDatabase = MapDatabaseFactory mapDatabase = MapDatabaseFactory
.createMapDatabase(MapDatabases.JSON_READER); .createMapDatabase(MapDatabases.JSON_READER);
} else { } else {
mapDatabase = MapDatabaseFactory.createMapDatabase(mapDatabaseType); mapDatabase = MapDatabaseFactory.createMapDatabase(mapDatabaseType);
} }
@ -180,16 +171,18 @@ public class MapView extends GLSurfaceView {
IMapGenerator mapGenerator = mMapRenderer.createMapGenerator(); IMapGenerator mapGenerator = mMapRenderer.createMapGenerator();
mapGenerator.setMapDatabase(mapDatabase); mapGenerator.setMapDatabase(mapDatabase);
if (i == 0) { if (i == 0)
mMapDatabase = mapDatabase; mMapDatabase = mapDatabase;
initMapStartPosition();
}
mMapWorkers[i] = new MapWorker(i, this, mapGenerator, mMapRenderer); mMapWorkers[i] = new MapWorker(i, this, mapGenerator, mMapRenderer);
mMapWorkers[i].start(); mMapWorkers[i].start();
} }
if (!setRenderTheme(InternalRenderTheme.OSMARENDER)) { setMapFile("default");
Log.d(TAG, "EEEK could parse theme"); initMapStartPosition();
if (!setRenderTheme(DEFAULT_RENDER_THEME)) {
Log.d(TAG, "X could not parse theme");
// FIXME show init error dialog // FIXME show init error dialog
} }
@ -197,11 +190,15 @@ public class MapView extends GLSurfaceView {
setEGLContextClientVersion(2); setEGLContextClientVersion(2);
setRenderer(mMapRenderer); setRenderer(mMapRenderer);
if (!debugFrameTime)
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
mapActivity.registerMapView(this); mapActivity.registerMapView(this);
} }
public final static boolean debugFrameTime = false;
private void initMapStartPosition() { private void initMapStartPosition() {
GeoPoint startPoint = getStartPoint(); GeoPoint startPoint = getStartPoint();
if (startPoint != null) { if (startPoint != null) {
@ -212,7 +209,6 @@ public class MapView extends GLSurfaceView {
if (startZoomLevel != null) { if (startZoomLevel != null) {
mMapViewPosition.setZoomLevel(startZoomLevel.byteValue()); mMapViewPosition.setZoomLevel(startZoomLevel.byteValue());
} }
} }
/** /**
@ -250,13 +246,6 @@ public class MapView extends GLSurfaceView {
return mMapFile; 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. * @return the current position and zoom level of this MapView.
*/ */
@ -264,20 +253,6 @@ public class MapView extends GLSurfaceView {
return mMapViewPosition; 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. * @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 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 @Override
public boolean onTouchEvent(MotionEvent motionEvent) { public boolean onTouchEvent(MotionEvent motionEvent) {
return mTouchEventHandler.handleMotionEvent(motionEvent); return mTouchEventHandler.handleMotionEvent(motionEvent);
} }
// @Override
// public boolean onTrackballEvent(MotionEvent motionEvent) {
// return mMapMover.onTrackballEvent(motionEvent);
// }
/** /**
* Calculates all necessary tiles and adds jobs accordingly. * Calculates all necessary tiles and adds jobs accordingly.
*/ */
@ -372,21 +325,13 @@ public class MapView extends GLSurfaceView {
public boolean setMapFile(String mapFile) { public boolean setMapFile(String mapFile) {
FileOpenResult fileOpenResult = null; FileOpenResult fileOpenResult = null;
Log.d(TAG, "set mapfile " + mapFile); Log.i(TAG, "set mapfile " + mapFile);
if (mapFile != null && mapFile.equals(mMapFile)) { if (mapFile != null && mapFile.equals(mMapFile)) {
// same map file as before // same map file as before
return false; return false;
} }
// mZoomAnimator.pause();
// mMapMover.pause();
// mZoomAnimator.awaitPausing();
// mMapMover.awaitPausing();
// mZoomAnimator.proceed();
// mMapMover.stopMove();
// mMapMover.proceed();
boolean initialized = false; boolean initialized = false;
mJobQueue.clear(); mJobQueue.clear();
@ -403,7 +348,7 @@ public class MapView extends GLSurfaceView {
if (mapFile != null) if (mapFile != null)
fileOpenResult = mapDatabase.openFile(new File(mapFile)); fileOpenResult = mapDatabase.openFile(new File(mapFile));
else else
fileOpenResult = mapDatabase.openFile(null); fileOpenResult = mapDatabase.openFile(cacheDir);
if (fileOpenResult != null && fileOpenResult.isSuccess()) { if (fileOpenResult != null && fileOpenResult.isSuccess()) {
mMapFile = mapFile; mMapFile = mapFile;
@ -417,12 +362,12 @@ public class MapView extends GLSurfaceView {
if (initialized) { if (initialized) {
clearAndRedrawMapView(); clearAndRedrawMapView();
Log.d(TAG, "mapfile set"); Log.i(TAG, "mapfile set");
return true; return true;
} }
mMapFile = null; mMapFile = null;
Log.d(TAG, "loading mapfile failed"); Log.i(TAG, "loading mapfile failed");
return false; return false;
} }
@ -430,6 +375,7 @@ public class MapView extends GLSurfaceView {
private GeoPoint getStartPoint() { private GeoPoint getStartPoint() {
if (mMapDatabase != null && mMapDatabase.hasOpenFile()) { if (mMapDatabase != null && mMapDatabase.hasOpenFile()) {
MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo(); MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo();
if (mapFileInfo.startPosition != null) { if (mapFileInfo.startPosition != null) {
return mapFileInfo.startPosition; return mapFileInfo.startPosition;
} else if (mapFileInfo.mapCenter != null) { } else if (mapFileInfo.mapCenter != null) {
@ -443,6 +389,7 @@ public class MapView extends GLSurfaceView {
private Byte getStartZoomLevel() { private Byte getStartZoomLevel() {
if (mMapDatabase != null && mMapDatabase.hasOpenFile()) { if (mMapDatabase != null && mMapDatabase.hasOpenFile()) {
MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo(); MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo();
if (mapFileInfo.startZoomLevel != null) { if (mapFileInfo.startZoomLevel != null) {
return mapFileInfo.startZoomLevel; return mapFileInfo.startZoomLevel;
} }
@ -464,7 +411,7 @@ public class MapView extends GLSurfaceView {
IMapGenerator mapGenerator; IMapGenerator mapGenerator;
Log.d(TAG, "setMapDatabase " + mapDatabaseType.name()); Log.i(TAG, "setMapDatabase " + mapDatabaseType.name());
if (mMapDatabaseType == mapDatabaseType) if (mMapDatabaseType == mapDatabaseType)
return; return;
@ -487,8 +434,6 @@ public class MapView extends GLSurfaceView {
setMapFile(mapFile); setMapFile(mapFile);
mapWorkersProceed(); mapWorkersProceed();
Log.d(TAG, ">>>");
} }
/** /**
@ -568,10 +513,10 @@ public class MapView extends GLSurfaceView {
* @param textScale * @param textScale
* the new text scale for the map rendering. * the new text scale for the map rendering.
*/ */
public void setTextScale(float textScale) { // public void setTextScale(float textScale) {
mJobParameters = new JobParameters(mJobParameters.theme, textScale); // mJobParameters = new JobParameters(mJobParameters.theme, textScale);
clearAndRedrawMapView(); // clearAndRedrawMapView();
} // }
/** /**
* Zooms in or out by the given amount of zoom levels. * Zooms in or out by the given amount of zoom levels.
@ -603,32 +548,10 @@ public class MapView extends GLSurfaceView {
return true; 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 @Override
protected synchronized void onSizeChanged(int width, int height, int oldWidth, protected synchronized void onSizeChanged(int width, int height, int oldWidth,
int oldHeight) { int oldHeight) {
mJobQueue.clear(); mJobQueue.clear();
mapWorkersPause(true); mapWorkersPause(true);
@ -639,9 +562,6 @@ public class MapView extends GLSurfaceView {
} }
void destroy() { void destroy() {
// mMapMover.interrupt();
// mZoomAnimator.interrupt();
for (MapWorker mapWorker : mMapWorkers) { for (MapWorker mapWorker : mMapWorkers) {
mapWorker.pause(); mapWorker.pause();
mapWorker.interrupt(); mapWorker.interrupt();
@ -655,9 +575,6 @@ public class MapView extends GLSurfaceView {
IMapDatabase mapDatabase = mapWorker.getMapGenerator().getMapDatabase(); IMapDatabase mapDatabase = mapWorker.getMapGenerator().getMapDatabase();
mapDatabase.closeFile(); mapDatabase.closeFile();
} }
// mMapScaleBar.destroy();
} }
/** /**
@ -693,18 +610,12 @@ public class MapView extends GLSurfaceView {
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
mapWorkersPause(false); mapWorkersPause(false);
// mMapMover.pause();
// mZoomAnimator.pause();
} }
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
mapWorkersProceed(); mapWorkersProceed();
// mMapMover.proceed();
// mZoomAnimator.proceed();
} }
/** /**
@ -715,34 +626,7 @@ public class MapView extends GLSurfaceView {
*/ */
void setCenterAndZoom(MapPosition mapPosition) { 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); mMapViewPosition.setMapCenterAndZoomLevel(mapPosition);
// mapZoomControls.onZoomLevelChange(mapViewPosition.getZoomLevel());
redrawTiles(); redrawTiles();
} }
@ -753,20 +637,17 @@ public class MapView extends GLSurfaceView {
return mMapViewPosition; return mMapViewPosition;
} }
/**
* @return current JobParameters
*/
public JobParameters getJobParameters() {
return mJobParameters;
}
/** /**
* add jobs and remember MapWorkers that stuff needs to be done * add jobs and remember MapWorkers that stuff needs to be done
* *
* @param jobs * @param jobs
* tile jobs * tile jobs
*/ */
public void addJobs(ArrayList<MapGeneratorJob> jobs) { public void addJobs(ArrayList<MapTile> jobs) {
if (jobs == null) {
mJobQueue.clear();
return;
}
mJobQueue.setJobs(jobs); mJobQueue.setJobs(jobs);
for (int i = 0; i < mNumMapWorkers; i++) { for (int i = 0; i < mNumMapWorkers; i++) {
@ -795,4 +676,17 @@ public class MapView extends GLSurfaceView {
mapWorker.proceed(); 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 org.mapsforge.core.MercatorProjection;
import android.util.FloatMath; import android.util.FloatMath;
import android.util.Log;
/** /**
* A MapPosition stores the latitude and longitude coordinate of a MapView together with its zoom level. * 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 final MapView mMapView;
private byte mZoomLevel; private byte mZoomLevel;
private float mScale; private float mScale;
private float mRotation;
// private float mRotation;
MapViewPosition(MapView mapView) { MapViewPosition(MapView mapView) {
mMapView = mapView; mMapView = mapView;
@ -43,7 +43,7 @@ public class MapViewPosition {
mLongitude = Double.NaN; mLongitude = Double.NaN;
mZoomLevel = -1; mZoomLevel = -1;
mScale = 1; mScale = 1;
// mRotation = 0.0f; mRotation = 0.0f;
} }
/** /**
@ -61,8 +61,7 @@ public class MapViewPosition {
if (!isValid()) { if (!isValid()) {
return null; return null;
} }
GeoPoint geoPoint = new GeoPoint(mLatitude, mLongitude); return new MapPosition(mLatitude, mLongitude, mZoomLevel, mScale, mRotation);
return new MapPosition(geoPoint, mZoomLevel, mScale);
} }
/** /**
@ -105,28 +104,50 @@ public class MapViewPosition {
/** /**
* Moves this MapViewPosition by the given amount of pixels. * Moves this MapViewPosition by the given amount of pixels.
* *
* @param moveHorizontal * @param mx
* the amount of pixels to move the map horizontally. * the amount of pixels to move the map horizontally.
* @param moveVertical * @param my
* the amount of pixels to move the map vertically. * 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 pixelX = MercatorProjection.longitudeToPixelX(mLongitude, mZoomLevel);
double pixelY = MercatorProjection.latitudeToPixelY(mLatitude, mZoomLevel); double pixelY = MercatorProjection.latitudeToPixelY(mLatitude, mZoomLevel);
mLatitude = MercatorProjection.pixelYToLatitude(pixelY - moveVertical / mScale, // float rad = (float) Math.toRadians(mRotation);
mZoomLevel); // 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); mLatitude = MercatorProjection.limitLatitude(mLatitude);
mLongitude = MercatorProjection.pixelXToLongitude(pixelX - moveHorizontal mLongitude = MercatorProjection.pixelXToLongitude(dx, mZoomLevel);
/ mScale,
mZoomLevel); //
mLongitude = MercatorProjection.limitLongitude(mLongitude); // 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) { public synchronized void rotateMap(float angle) {
// mRotation = angle; mRotation -= angle;
// } Log.d("...", "angle:" + mRotation);
// mRotation %= 360;
}
synchronized void setMapCenter(GeoPoint geoPoint) { synchronized void setMapCenter(GeoPoint geoPoint) {
mLatitude = MercatorProjection.limitLatitude(geoPoint.getLatitude()); mLatitude = MercatorProjection.limitLatitude(geoPoint.getLatitude());
@ -134,9 +155,8 @@ public class MapViewPosition {
} }
synchronized void setMapCenterAndZoomLevel(MapPosition mapPosition) { synchronized void setMapCenterAndZoomLevel(MapPosition mapPosition) {
GeoPoint geoPoint = mapPosition.geoPoint; mLatitude = MercatorProjection.limitLatitude(mapPosition.lat);
mLatitude = MercatorProjection.limitLatitude(geoPoint.getLatitude()); mLongitude = MercatorProjection.limitLongitude(mapPosition.lon);
mLongitude = MercatorProjection.limitLongitude(geoPoint.getLongitude());
mZoomLevel = mMapView.limitZoomLevel(mapPosition.zoomLevel); mZoomLevel = mMapView.limitZoomLevel(mapPosition.zoomLevel);
} }
@ -157,6 +177,7 @@ public class MapViewPosition {
* ... * ...
*/ */
public synchronized void scaleMap(float scale, float pivotX, float pivotY) { public synchronized void scaleMap(float scale, float pivotX, float pivotY) {
if (pivotY != 0 || pivotY != 0)
moveMap(pivotX * (1.0f - scale), moveMap(pivotX * (1.0f - scale),
pivotY * (1.0f - scale)); pivotY * (1.0f - scale));

View File

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

View File

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

View File

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

View File

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

View File

@ -14,8 +14,10 @@
*/ */
package org.mapsforge.android.glrenderer; 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.IMapGenerator;
import org.mapsforge.android.mapgenerator.MapGeneratorJob; import org.mapsforge.android.mapgenerator.MapTile;
import org.mapsforge.android.rendertheme.IRenderCallback; import org.mapsforge.android.rendertheme.IRenderCallback;
import org.mapsforge.android.rendertheme.RenderTheme; import org.mapsforge.android.rendertheme.RenderTheme;
import org.mapsforge.android.rendertheme.renderinstruction.Area; import org.mapsforge.android.rendertheme.renderinstruction.Area;
@ -81,12 +83,24 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
private RenderInstruction[] mRenderInstructions = null; private RenderInstruction[] mRenderInstructions = null;
private final String TAG_WATER = "water".intern(); 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"); Log.d(TAG, "init DatabaseRenderer");
mMapView = mapView;
} }
private float mPoiX = 256; private float mPoiX = 256;
@ -115,8 +129,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
if (mMapProjection != null) if (mMapProjection != null)
{ {
long x = mCurrentTile.x; long x = mCurrentTile.pixelX;
long y = mCurrentTile.y; long y = mCurrentTile.pixelY + Tile.TILE_SIZE;
long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel; long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel;
double divx, divy; double divx, divy;
@ -163,6 +177,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mTagName = null; mTagName = null;
mProjected = false; mProjected = false;
mCurLineLayer = null;
mDrawingLayer = getValidLayer(layer) * mLevels; mDrawingLayer = getValidLayer(layer) * mLevels;
mSimplify = 0.5f; mSimplify = 0.5f;
@ -325,9 +340,10 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
} }
} }
if (lineLayer == null) if (lineLayer == null) {
mCurLineLayer = null;
return; return;
}
if (line.outline) { if (line.outline) {
lineLayer.addOutline(mCurLineLayer); lineLayer.addOutline(mCurLineLayer);
return; return;
@ -355,45 +371,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
} }
pos += length; 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 @Override
@ -469,20 +446,27 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
boolean mDebugDrawUnmatched; boolean mDebugDrawUnmatched;
@Override @Override
public boolean executeJob(MapGeneratorJob mapGeneratorJob) { public boolean executeJob(MapTile mapTile) {
GLMapTile tile; GLMapTile tile;
if (mMapDatabase == null) if (mMapDatabase == null)
return false; return false;
tile = mCurrentTile = (GLMapTile) mapGeneratorJob.tile; tile = mCurrentTile = (GLMapTile) mapTile;
mDebugDrawPolygons = !mapGeneratorJob.debugSettings.mDisablePolygons; DebugSettings debugSettings = mMapView.getDebugSettings();
mDebugDrawUnmatched = mapGeneratorJob.debugSettings.mDrawUnmatchted;
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; return false;
}
tile.isLoading = true;
mLevels = MapGenerator.renderTheme.getLevels(); mLevels = MapGenerator.renderTheme.getLevels();
@ -492,10 +476,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
else else
setScaleStrokeWidth(STROKE_MAX_ZOOM_LEVEL); setScaleStrokeWidth(STROKE_MAX_ZOOM_LEVEL);
mLineLayers = null;
mPolyLayers = null;
mLabels = null;
// firstMatch = true; // firstMatch = true;
countLines = 0; countLines = 0;
countNodes = 0; countNodes = 0;
@ -516,12 +496,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
return false; return false;
} }
if (mapGeneratorJob.debugSettings.mDrawTileFrames) { if (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 };
mTagName = new Tag("name", countLines + " " + countNodes + " " mTagName = new Tag("name", countLines + " " + countNodes + " "
+ tile.toString(), false); + tile.toString(), false);
mPoiX = Tile.TILE_SIZE >> 1; mPoiX = Tile.TILE_SIZE >> 1;
@ -533,21 +508,20 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mDrawingLayer = 10 * mLevels; mDrawingLayer = 10 * mLevels;
MapGenerator.renderTheme.matchWay(this, debugTagBox, (byte) 0, false, true); MapGenerator.renderTheme.matchWay(this, debugTagBox, (byte) 0, false, true);
} }
tile.lineLayers = mLineLayers; tile.lineLayers = mLineLayers;
tile.polygonLayers = mPolyLayers; tile.polygonLayers = mPolyLayers;
tile.labels = mLabels; tile.labels = mLabels;
mCurPolyLayer = null; mCurPolyLayer = null;
mCurLineLayer = null; mCurLineLayer = null;
mLineLayers = null;
mPolyLayers = null;
mLabels = null;
return true; 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) { private static byte getValidLayer(byte layer) {
if (layer < 0) { if (layer < 0) {
return 0; return 0;
@ -612,8 +586,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
float[] coords = mWayNodes; float[] coords = mWayNodes;
long x = mCurrentTile.x; long x = mCurrentTile.pixelX;
long y = mCurrentTile.y; long y = mCurrentTile.pixelY + Tile.TILE_SIZE;
long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel; long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel;
float min = mSimplify; 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 // do not modify stencil buffer
glStencilMask(0); glStencilMask(0);
// clip with depth mask GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
// GLES20.glEnable(GLES20.GL_DEPTH_TEST);
// glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
for (int c = 0; c < count; c++) { for (int c = 0; c < count; c++) {
PolygonLayer l = mFillPolys[c]; PolygonLayer l = mFillPolys[c];
@ -139,13 +137,10 @@ class PolygonLayers {
if (blend) if (blend)
glDisable(GL_BLEND); glDisable(GL_BLEND);
// glDisable(GLES20.GL_DEPTH_TEST);
// glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
} }
static PolygonLayer drawPolygons(PolygonLayer layer, int next, 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; int cnt = 0;
glUseProgram(polygonProgram); glUseProgram(polygonProgram);
@ -182,10 +177,8 @@ class PolygonLayers {
// clear stencilbuffer (tile region) // clear stencilbuffer (tile region)
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
// draw depth clipper
if (first) { if (first) {
// glEnable(GLES20.GL_DEPTH_TEST);
// glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
GLES20.glPolygonOffset(0, drawCount);
GLES20.glDepthMask(true); GLES20.glDepthMask(true);
GLES20.glDepthFunc(GLES20.GL_LESS); GLES20.glDepthFunc(GLES20.GL_LESS);
} }
@ -196,13 +189,16 @@ class PolygonLayers {
first = false; first = false;
GLES20.glDepthMask(false); GLES20.glDepthMask(false);
GLES20.glDepthFunc(GLES20.GL_EQUAL); GLES20.glDepthFunc(GLES20.GL_EQUAL);
// glDisable(GLES20.GL_DEPTH_TEST);
} }
// stencil op for stencil method polygon drawing // stencil op for stencil method polygon drawing
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
} }
//
mFillPolys[cnt] = l; mFillPolys[cnt] = l;
// set stencil mask to draw to // set stencil mask to draw to
@ -223,7 +219,7 @@ class PolygonLayers {
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
if (clip && first) if (clip && first)
drawDepthClip(drawCount); drawDepthClip();
// required on GalaxyII, Android 2.3.3 (cant just VAA enable once...) // required on GalaxyII, Android 2.3.3 (cant just VAA enable once...)
GLES20.glDisableVertexAttribArray(hPolygonVertexPosition); GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
@ -231,53 +227,16 @@ class PolygonLayers {
return l; return l;
} }
// static void drawStencilClip(byte drawCount) { static void drawDepthClip() {
// // 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) {
glColorMask(false, false, false, false); glColorMask(false, false, false, false);
// glEnable(GLES20.GL_DEPTH_TEST);
// glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
GLES20.glPolygonOffset(0, drawCount);
GLES20.glDepthMask(true); GLES20.glDepthMask(true);
GLES20.glDepthFunc(GLES20.GL_LESS); GLES20.glDepthFunc(GLES20.GL_LESS);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
GLES20.glDepthMask(false); GLES20.glDepthMask(false);
glColorMask(true, true, true, true); glColorMask(true, true, true, true);
GLES20.glDepthFunc(GLES20.GL_EQUAL); GLES20.glDepthFunc(GLES20.GL_EQUAL);
} }

View File

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

View File

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

View File

@ -45,7 +45,6 @@ public class TextRenderer {
private static int mFontPadY = 1; private static int mFontPadY = 1;
private static int mBitmapFormat; private static int mBitmapFormat;
private static int mBitmapType; private static int mBitmapType;
private static ByteBuffer mByteBuffer;
private static ShortBuffer mShortBuffer; private static ShortBuffer mShortBuffer;
private static TextTexture[] mTextures; private static TextTexture[] mTextures;
@ -57,9 +56,8 @@ public class TextRenderer {
private static int hTextVertex; private static int hTextVertex;
private static int hTextScale; private static int hTextScale;
private static int hTextTextureCoord; 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 boolean debug = false;
private static short[] debugVertices = { private static short[] debugVertices = {
@ -79,13 +77,24 @@ public class TextRenderer {
}; };
static boolean init(int numTextures) { static boolean init(int numTextures) {
mBitmap = Bitmap int bufferSize = numTextures
.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT, Bitmap.Config.ARGB_8888); * 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); mCanvas = new Canvas(mBitmap);
mBitmapFormat = GLUtils.getInternalFormat(mBitmap); mBitmapFormat = GLUtils.getInternalFormat(mBitmap);
mBitmapType = GLUtils.getType(mBitmap); mBitmapType = GLUtils.getType(mBitmap);
ByteBuffer buf = ByteBuffer.allocateDirect(bufferSize)
.order(ByteOrder.nativeOrder());
mShortBuffer = buf.asShortBuffer();
// }
mTextProgram = GlUtils.createProgram(Shaders.textVertexShader, mTextProgram = GlUtils.createProgram(Shaders.textVertexShader,
Shaders.textFragmentShader); Shaders.textFragmentShader);
@ -94,15 +103,6 @@ public class TextRenderer {
hTextScale = GLES20.glGetUniformLocation(mTextProgram, "scale"); hTextScale = GLES20.glGetUniformLocation(mTextProgram, "scale");
hTextTextureCoord = GLES20.glGetAttribLocation(mTextProgram, "tex_coord"); 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]; int[] textureIds = new int[numTextures];
TextTexture[] textures = new TextTexture[numTextures]; TextTexture[] textures = new TextTexture[numTextures];
GLES20.glGenTextures(numTextures, textureIds, 0); GLES20.glGenTextures(numTextures, textureIds, 0);
@ -136,24 +136,23 @@ public class TextRenderer {
int len = indices.length; int len = indices.length;
short j = 0; short j = 0;
for (int i = 0; i < len; i += INDICES_PER_SPRITE, j += VERTICES_PER_SPRITE) { 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 + 0] = (short) (j + 0);
indices[i + 1] = (short) (j + 0); indices[i + 1] = (short) (j + 1);
indices[i + 2] = (short) (j + 1); indices[i + 2] = (short) (j + 2);
indices[i + 3] = (short) (j + 3); indices[i + 3] = (short) (j + 2);
indices[i + 4] = (short) (j + 2); indices[i + 4] = (short) (j + 3);
indices[i + 5] = (short) (j + 2); 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(); mShortBuffer.clear();
mShortBuffer.put(indices, 0, len);
tmpIndices.put(indices, 0, len); mShortBuffer.flip();
tmpIndices.flip();
int[] mVboIds = new int[2]; int[] mVboIds = new int[2];
GLES20.glGenBuffers(2, mVboIds, 0); GLES20.glGenBuffers(2, mVboIds, 0);
@ -162,13 +161,15 @@ public class TextRenderer {
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, len * (Short.SIZE / 8), 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); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
mShortBuffer.clear();
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, bufferSize, GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, bufferSize,
mShortBuffer, GLES20.GL_DYNAMIC_DRAW); mShortBuffer, GLES20.GL_DYNAMIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
return true; return true;
} }
@ -360,10 +361,13 @@ public class TextRenderer {
tex.length = pos; tex.length = pos;
tile.texture = tex; tile.texture = tex;
tex.tile = tile; tex.tile = tile;
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex.id); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex.id);
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mBitmap, GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mBitmap,
mBitmapFormat, mBitmapType); mBitmapFormat, mBitmapType);
GLES20.glFlush();
return true; return true;
} }
@ -388,9 +392,7 @@ public class TextRenderer {
} }
mShortBuffer.flip(); 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), GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, offset * (Short.SIZE / 8),
mShortBuffer); mShortBuffer);
} }
@ -442,7 +444,7 @@ public class TextRenderer {
GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8) GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8)
+ 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); 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; // private static final int DISTANCE_BETWEEN_SYMBOLS = 200;
/** // /**
* Minimum distance in pixels before the way name is repeated. // * Minimum distance in pixels before the way name is repeated.
*/ // */
private static final int DISTANCE_BETWEEN_WAY_NAMES = 500; // private static final int DISTANCE_BETWEEN_WAY_NAMES = 500;
// /** // /**
// * Distance in pixels to skip from both ends of a segment. // * 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.MapView;
import org.mapsforge.android.MapViewPosition; import org.mapsforge.android.MapViewPosition;
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.view.ScaleGestureDetector; import android.view.ScaleGestureDetector;
import android.view.animation.DecelerateInterpolator;
class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener { class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener {
private final MapView mMapView; private final MapView mMapView;
private MapViewPosition mMapPosition; private MapViewPosition mMapPosition;
private float mCenterX; private float mCenterX;
private float mCenterY; private float mCenterY;
// private float mFocusX;
// private float mFocusY;
private float mScale; private float mScale;
private boolean mBeginScale;
// private boolean mScaling;
/** /**
* Creates a new ScaleListener for the given MapView. * Creates a new ScaleListener for the given MapView.
* *
@ -40,52 +41,104 @@ class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener {
} }
@Override @Override
public boolean onScale(ScaleGestureDetector scaleGestureDetector) { public boolean onScale(ScaleGestureDetector gd) {
float focusX = scaleGestureDetector.getFocusX(); float focusX = gd.getFocusX();
float focusY = scaleGestureDetector.getFocusY(); float focusY = gd.getFocusY();
mScale = scaleGestureDetector.getScaleFactor(); mScale = gd.getScaleFactor();
// mMapPosition.moveMap((focusX - mFocusX), (focusY - mFocusY)); mSumScale *= mScale;
// if (mScale > 1.001 || mScale < 0.999) {
mMapPosition.scaleMap(mScale, mTimeEnd = SystemClock.elapsedRealtime();
focusX - mCenterX,
focusY - mCenterY); if (!mBeginScale) {
if (mTimeEnd - mTimeStart > 100) {
mBeginScale = true;
mScale = mSumScale;
}
else
return true;
}
mMapPosition.scaleMap(mScale, focusX - mCenterX, focusY - mCenterY);
mMapView.redrawTiles(); 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; return true;
} }
@Override private long mTimeStart;
public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) { private long mTimeEnd;
private float mSumScale;
@Override
public boolean onScaleBegin(ScaleGestureDetector gd) {
mTimeEnd = mTimeStart = SystemClock.elapsedRealtime();
mSumScale = 1;
mBeginScale = false;
mCenterX = mMapView.getWidth() >> 1; mCenterX = mMapView.getWidth() >> 1;
mCenterY = mMapView.getHeight() >> 1; mCenterY = mMapView.getHeight() >> 1;
// mFocusX = scaleGestureDetector.getFocusX();
// mFocusY = scaleGestureDetector.getFocusY();
mScale = 1; mScale = 1;
mMapPosition = mMapView.getMapPosition(); mMapPosition = mMapView.getMapPosition();
// mScaling = false;
return true; return true;
} }
@Override @Override
public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) { public void onScaleEnd(ScaleGestureDetector gd) {
// do nothing // 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; package org.mapsforge.android.input;
import org.mapsforge.android.MapView; import org.mapsforge.android.MapView;
import org.mapsforge.android.MapViewPosition;
import org.mapsforge.core.Tile; import org.mapsforge.core.Tile;
import android.content.Context; import android.content.Context;
import android.os.CountDownTimer; import android.os.CountDownTimer;
import android.util.Log;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener; import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.ScaleGestureDetector; import android.view.ScaleGestureDetector;
import android.view.ViewConfiguration; import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller; import android.widget.Scroller;
/** /**
@ -33,15 +34,15 @@ import android.widget.Scroller;
public class TouchHandler { public class TouchHandler {
private static final int INVALID_POINTER_ID = -1; private static final int INVALID_POINTER_ID = -1;
/**
* is pritected correct? share MapView with inner class
*/
protected final MapView mMapView; protected final MapView mMapView;
protected final MapViewPosition mMapPosition;
private final float mMapMoveDelta; private final float mMapMoveDelta;
private boolean mMoveThresholdReached; private boolean mMoveThresholdReached;
private float mPreviousPositionX; private float mPosX;
private float mPreviousPositionY; private float mPosY;
private float mAngle;
private int mActivePointerId; private int mActivePointerId;
private final ScaleGestureDetector mScaleGestureDetector; private final ScaleGestureDetector mScaleGestureDetector;
@ -56,11 +57,13 @@ public class TouchHandler {
public TouchHandler(Context context, MapView mapView) { public TouchHandler(Context context, MapView mapView) {
ViewConfiguration viewConfiguration = ViewConfiguration.get(context); ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
mMapView = mapView; mMapView = mapView;
mMapPosition = mapView.getMapPosition();
mMapMoveDelta = viewConfiguration.getScaledTouchSlop(); mMapMoveDelta = viewConfiguration.getScaledTouchSlop();
mActivePointerId = INVALID_POINTER_ID; mActivePointerId = INVALID_POINTER_ID;
mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener( mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener(
mMapView)); mMapView));
mGestureDetector = new GestureDetector(new MapGestureDetector(mMapView)); mGestureDetector = new GestureDetector(context, new MapGestureDetector(mMapView));
} }
private static int getAction(MotionEvent motionEvent) { private static int getAction(MotionEvent motionEvent) {
@ -72,22 +75,30 @@ public class TouchHandler {
return true; return true;
} }
private boolean onActionDown(MotionEvent motionEvent) { private boolean onActionDown(MotionEvent event) {
mPreviousPositionX = motionEvent.getX(); mPosX = event.getX();
mPreviousPositionY = motionEvent.getY(); mPosY = event.getY();
mMoveThresholdReached = false; mMoveThresholdReached = false;
// save the ID of the pointer // save the ID of the pointer
mActivePointerId = motionEvent.getPointerId(0); mActivePointerId = event.getPointerId(0);
// Log.d("...", "set active pointer" + mActivePointerId);
return true; return true;
} }
private boolean onActionMove(MotionEvent motionEvent) { private boolean mScaling = false;
int pointerIndex = motionEvent.findPointerIndex(mActivePointerId);
private boolean onActionMove(MotionEvent event) {
int pointerIndex = event.findPointerIndex(mActivePointerId);
// calculate the distance between previous and current position // calculate the distance between previous and current position
float moveX = motionEvent.getX(pointerIndex) - mPreviousPositionX; float moveX = event.getX(pointerIndex) - mPosX;
float moveY = motionEvent.getY(pointerIndex) - mPreviousPositionY; float moveY = event.getY(pointerIndex) - mPosY;
boolean scaling = mScaleGestureDetector.isInProgress(); boolean scaling = mScaleGestureDetector.isInProgress();
if (!mScaling) {
mScaling = scaling;
}
if (!scaling && !mMoveThresholdReached) { if (!scaling && !mMoveThresholdReached) {
if (Math.abs(moveX) > 3 * mMapMoveDelta if (Math.abs(moveX) > 3 * mMapMoveDelta
@ -97,36 +108,57 @@ public class TouchHandler {
mMoveThresholdReached = true; mMoveThresholdReached = true;
// save the position of the event // save the position of the event
mPreviousPositionX = motionEvent.getX(pointerIndex); mPosX = event.getX(pointerIndex);
mPreviousPositionY = motionEvent.getY(pointerIndex); mPosY = event.getY(pointerIndex);
} }
return true; 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 // save the position of the event
mPreviousPositionX = motionEvent.getX(pointerIndex); mPosX = event.getX(pointerIndex);
mPreviousPositionY = motionEvent.getY(pointerIndex); mPosY = event.getY(pointerIndex);
if (scaling) { if (scaling) {
return true; return true;
} }
mMapView.getMapPosition().moveMap(moveX, moveY); mMapPosition.moveMap(moveX, moveY);
mMapView.redrawTiles(); mMapView.redrawTiles();
return true; return true;
} }
// private boolean onActionPointerDown(MotionEvent motionEvent) { private int multi = 0;
private boolean onActionPointerDown(MotionEvent event) {
// longPressDetector.pressStop(); // longPressDetector.pressStop();
// multiTouchDownTime = motionEvent.getEventTime(); // multiTouchDownTime = motionEvent.getEventTime();
// return true; 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) { private boolean onActionPointerUp(MotionEvent motionEvent) {
// extract the index of the pointer that left the touch sensor // 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; int pointerIndex = (motionEvent.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
if (motionEvent.getPointerId(pointerIndex) == mActivePointerId) { if (motionEvent.getPointerId(pointerIndex) == mActivePointerId) {
// the active pointer has gone up, choose a new one // the active pointer has gone up, choose a new one
if (pointerIndex == 0) { if (pointerIndex == 0) {
@ -135,19 +167,12 @@ public class TouchHandler {
pointerIndex = 0; pointerIndex = 0;
} }
// save the position of the event // save the position of the event
mPreviousPositionX = motionEvent.getX(pointerIndex); mPosX = motionEvent.getX(pointerIndex);
mPreviousPositionY = motionEvent.getY(pointerIndex); mPosY = motionEvent.getY(pointerIndex);
mActivePointerId = motionEvent.getPointerId(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; return true;
} }
@ -157,83 +182,53 @@ public class TouchHandler {
* @return ... * @return ...
*/ */
private boolean onActionUp(MotionEvent motionEvent) { private boolean onActionUp(MotionEvent motionEvent) {
// longPressDetector.pressStop();
// int pointerIndex = motionEvent.findPointerIndex(mActivePointerId);
mActivePointerId = INVALID_POINTER_ID; mActivePointerId = INVALID_POINTER_ID;
// if (mMoveThresholdReached // || longPressDetector.isEventHandled() mScaling = false;
// ) {
// 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();
//
// }
return true; return true;
} }
private long lastRun = 0;
/** /**
* @param motionEvent * @param event
* ... * ...
* @return ... * @return ...
*/ */
public boolean handleMotionEvent(MotionEvent motionEvent) { public boolean handleMotionEvent(MotionEvent event) {
// workaround for a bug in the ScaleGestureDetector, see Android issue // workaround for a bug in the ScaleGestureDetector, see Android issue
// #12976 // #12976
if (motionEvent.getAction() != MotionEvent.ACTION_MOVE // if (event.getAction() != MotionEvent.ACTION_MOVE
|| motionEvent.getPointerCount() > 1) { // || event.getPointerCount() > 1) {
mScaleGestureDetector.onTouchEvent(motionEvent); mScaleGestureDetector.onTouchEvent(event);
}
mGestureDetector.onTouchEvent(motionEvent);
// if () {
// // mActivePointerId = INVALID_POINTER_ID;
// // return true;
// } // }
int action = getAction(motionEvent);
if (!mScaling)
mGestureDetector.onTouchEvent(event);
int action = getAction(event);
boolean ret = false; boolean ret = false;
if (action == MotionEvent.ACTION_DOWN) { if (action == MotionEvent.ACTION_DOWN) {
ret = onActionDown(motionEvent); ret = onActionDown(event);
} else if (action == MotionEvent.ACTION_MOVE) { } else if (action == MotionEvent.ACTION_MOVE) {
ret = onActionMove(motionEvent); ret = onActionMove(event);
} else if (action == MotionEvent.ACTION_UP) { } else if (action == MotionEvent.ACTION_UP) {
ret = onActionUp(motionEvent); ret = onActionUp(event);
} else if (action == MotionEvent.ACTION_CANCEL) { } else if (action == MotionEvent.ACTION_CANCEL) {
ret = onActionCancel(); ret = onActionCancel();
// } else if (action == MotionEvent.ACTION_POINTER_DOWN) { } else if (action == MotionEvent.ACTION_POINTER_DOWN) {
// return onActionPointerDown(motionEvent); return onActionPointerDown(event);
} else if (action == MotionEvent.ACTION_POINTER_UP) { } 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; return ret;
} }
class MapGestureDetector extends SimpleOnGestureListener { class MapGestureDetector extends SimpleOnGestureListener {
private Scroller mScroller; private Scroller mScroller;
private float mPrevX, mPrevY; private float mPrevX, mPrevY, mPrevScale;
private CountDownTimer mTimer = null; private CountDownTimer mTimer = null;
private boolean fling = false;
public MapGestureDetector(MapView mapView) { public MapGestureDetector(MapView mapView) {
mScroller = new Scroller(mapView.getContext(), mScroller = new Scroller(mapView.getContext(),
@ -242,12 +237,17 @@ public class TouchHandler {
@Override @Override
public boolean onDown(MotionEvent e) { public boolean onDown(MotionEvent e) {
if (fling) {
mScroller.forceFinished(true); mScroller.forceFinished(true);
if (mTimer != null) { if (mTimer != null) {
mTimer.cancel(); mTimer.cancel();
mTimer = null; mTimer = null;
} }
fling = false;
}
// Log.d("mapsforge", "onDown");
return true; return true;
} }
@ -256,11 +256,12 @@ public class TouchHandler {
return false; return false;
} }
mScroller.computeScrollOffset(); mScroller.computeScrollOffset();
float moveX = mScroller.getCurrX() - mPrevX; float moveX = mScroller.getCurrX() - mPrevX;
float moveY = mScroller.getCurrY() - mPrevY; float moveY = mScroller.getCurrY() - mPrevY;
if (moveX >= 1 || moveY >= 1 || moveX <= -1 || moveY <= -1) { if (moveX >= 1 || moveY >= 1 || moveX <= -1 || moveY <= -1) {
mMapView.getMapPosition().moveMap(moveX, moveY); mMapPosition.moveMap(moveX, moveY);
mMapView.redrawTiles(); mMapView.redrawTiles();
mPrevX = mScroller.getCurrX(); mPrevX = mScroller.getCurrX();
mPrevY = mScroller.getCurrY(); mPrevY = mScroller.getCurrY();
@ -271,8 +272,8 @@ public class TouchHandler {
@Override @Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) { float velocityY) {
int w = Tile.TILE_SIZE * 10; int w = Tile.TILE_SIZE * 20;
int h = Tile.TILE_SIZE * 10; int h = Tile.TILE_SIZE * 20;
mPrevX = 0; mPrevX = 0;
mPrevY = 0; mPrevY = 0;
@ -283,12 +284,12 @@ public class TouchHandler {
mScroller.fling(0, 0, Math.round(velocityX) / 2, Math.round(velocityY) / 2, mScroller.fling(0, 0, Math.round(velocityX) / 2, Math.round(velocityY) / 2,
-w, w, -h, h); -w, w, -h, h);
// animate for two seconds // animate for two seconds
mTimer = new CountDownTimer(2000, 40) { mTimer = new CountDownTimer(1500, 50) {
@Override @Override
public void onTick(long tick) { public void onTick(long tick) {
if (!scroll()) scroll();
cancel();
} }
@Override @Override
@ -296,21 +297,61 @@ public class TouchHandler {
// do nothing // do nothing
} }
}.start(); }.start();
fling = true;
return true; return true;
} }
private DecelerateInterpolator mBounce = new DecelerateInterpolator();
@Override @Override
public void onLongPress(MotionEvent e) { public void onLongPress(MotionEvent e) {
// mMapView.zoom((byte) 1); // mMapView.zoom((byte) 1);
Log.d("mapsforge", "long press"); // Log.d("mapsforge", "long press");
// return true; }
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 @Override
public boolean onDoubleTap(MotionEvent e) { 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; return true;
} }
} }

View File

@ -29,11 +29,11 @@ public interface IMapGenerator {
/** /**
* Called when a job needs to be executed. * Called when a job needs to be executed.
* *
* @param mapGeneratorJob * @param tile
* the job that should be executed. * the job that should be executed.
* @return true if the job was executed successfully, false otherwise. * @return true if the job was executed successfully, false otherwise.
*/ */
boolean executeJob(MapGeneratorJob mapGeneratorJob); boolean executeJob(MapTile tile);
/** /**
* @param mapDatabase * @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.ArrayList;
import java.util.PriorityQueue; 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. * A JobQueue keeps the list of pending jobs for a MapView and prioritizes them.
*/ */
public class JobQueue { public class JobQueue {
private static final int INITIAL_CAPACITY = 128; private static final int INITIAL_CAPACITY = 64;
private final MapView mMapView; private PriorityQueue<MapTile> mPriorityQueue;
private PriorityQueue<MapGeneratorJob> mPriorityQueue;
private boolean mScheduleNeeded;
/** /**
* @param mapView
* the MapView whose jobs should be organized.
*/ */
public JobQueue(MapView mapView) { public JobQueue() {
mMapView = mapView; mPriorityQueue = new PriorityQueue<MapTile>(INITIAL_CAPACITY);
mPriorityQueue = new PriorityQueue<MapGeneratorJob>(INITIAL_CAPACITY);
} }
/** /**
* Adds the given job to this queue. Does nothing if the given job is already in this queue. * @param tiles
*
* @param mapGeneratorJob
* the job to be added to this queue. * the job to be added to this queue.
*/ */
// public synchronized void addJob(MapGeneratorJob mapGeneratorJob) { public synchronized void setJobs(ArrayList<MapTile> tiles) {
// 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) {
mPriorityQueue.clear(); mPriorityQueue.clear();
for (MapGeneratorJob job : jobs) mPriorityQueue.addAll(tiles);
mPriorityQueue.offer(job); // for (int i = 0, n = tiles.size(); i < n; i++)
// priorityQueue.addAll(jobs); // mPriorityQueue.offer(tiles.get(i));
mScheduleNeeded = true;
} }
/** /**
@ -84,39 +59,11 @@ public class JobQueue {
/** /**
* @return the most important job from this queue or null, if empty. * @return the most important job from this queue or null, if empty.
*/ */
public synchronized MapGeneratorJob poll() { public synchronized MapTile poll() {
if (mScheduleNeeded) { MapTile tile = mPriorityQueue.poll();
mScheduleNeeded = false; if (tile != null)
schedule(); tile.isLoading = true;
}
return mPriorityQueue.poll();
}
/** 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, String mapDatabaseName = attributeSet.getAttributeValue(null,
MAP_DATABASE_ATTRIBUTE_NAME); MAP_DATABASE_ATTRIBUTE_NAME);
if (mapDatabaseName == null) { if (mapDatabaseName == null) {
return MapDatabases.POSTGIS_READER; return MapDatabases.PBMAP_READER;
} }
return MapDatabases.valueOf(mapDatabaseName); 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). * 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 * @param zoomLevel
* .. * ..
*/ */
public MapTile(long tileX, long tileY, byte zoomLevel) { public MapTile(int tileX, int tileY, byte zoomLevel) {
super(tileX, tileY, 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 @Override
protected void doWork() { protected void doWork() {
MapGeneratorJob mapGeneratorJob = mJobQueue.poll(); MapTile tile = mJobQueue.poll();
if (mMapGenerator == null || mapGeneratorJob == null) if (mMapGenerator == null || tile == null)
return; return;
boolean success = mMapGenerator.executeJob(mapGeneratorJob); boolean success = mMapGenerator.executeJob(tile);
if (!isInterrupted() && success) { 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.InputStream;
import java.io.Serializable; import java.io.Serializable;
/**
* A JobTheme defines the render theme which is used for a {@link MapGeneratorJob}.
*/
public interface Theme extends Serializable { public interface Theme extends Serializable {
/** /**
* @return an InputStream to read the render theme data from. * @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 area
* ... * ...
* @param level
* ...
*/ */
void renderArea(Area area, int level); void renderArea(Area area, int level);
@ -83,6 +85,8 @@ public interface IRenderCallback {
* *
* @param line * @param line
* ... * ...
* @param level
* ...
*/ */
void renderWay(Line line, int 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> * @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; private final String mPath;

View File

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

View File

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

View File

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

View File

@ -485,7 +485,7 @@
</rule> </rule>
<!-- outline 1 - 4 --> <!-- 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="1" stroke="#404030"/> -->
<style-outline name="2" stroke="#c0c0c0" /> <style-outline name="2" stroke="#c0c0c0" />
<style-outline name="primary" stroke="#7f7700" width="0.025"/> <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 * @param zoomLevel
* .. * ..
*/ */
public GLMapTile(long tileX, long tileY, byte zoomLevel) { public GLMapTile(int tileX, int tileY, byte zoomLevel) {
super(tileX, tileY, zoomLevel); super(tileX, tileY, zoomLevel);
mScale = 1; mScale = 1;
mTextureID = -1; mTextureID = -1;

View File

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

View File

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

View File

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

View File

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

View File

@ -14,21 +14,16 @@
*/ */
package org.mapsforge.core; 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. * 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. * Conversion factor from degrees to microdegrees.
*/ */
private static final double CONVERSION_FACTOR = 1000000d; private static final double CONVERSION_FACTOR = 1000000d;
private static final long serialVersionUID = 1L;
/** /**
* The latitude value of this GeoPoint in microdegrees (degrees * 10^6). * 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. * The hash code of this object.
*/ */
private transient int hashCodeValue; private int hashCodeValue = 0;
/** /**
* @param latitude * @param latitude
@ -57,7 +52,6 @@ public class GeoPoint implements Comparable<GeoPoint>, Serializable {
double limitLongitude = MercatorProjection.limitLongitude(longitude); double limitLongitude = MercatorProjection.limitLongitude(longitude);
this.longitudeE6 = (int) (limitLongitude * CONVERSION_FACTOR); this.longitudeE6 = (int) (limitLongitude * CONVERSION_FACTOR);
this.hashCodeValue = calculateHashCode();
} }
/** /**
@ -116,6 +110,9 @@ public class GeoPoint implements Comparable<GeoPoint>, Serializable {
@Override @Override
public int hashCode() { public int hashCode() {
if (this.hashCodeValue == 0)
this.hashCodeValue = calculateHashCode();
return this.hashCodeValue; return this.hashCodeValue;
} }
@ -139,9 +136,4 @@ public class GeoPoint implements Comparable<GeoPoint>, Serializable {
result = 31 * result + this.longitudeE6; result = 31 * result + this.longitudeE6;
return result; 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; 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. * A MapPosition represents an immutable pair of {@link GeoPoint} and zoom level.
*/ */
public class MapPosition implements Serializable { public class MapPosition {
private static final long serialVersionUID = 1L;
/** /**
* The map position. * The map position.
*/ */
public final GeoPoint geoPoint; // public final GeoPoint geoPoint;
public final double lon;
public final double lat;
/** /**
* The zoom level. * The zoom level.
@ -38,10 +35,11 @@ public class MapPosition implements Serializable {
* 1.0 - 2.0 scale of current zoomlevel * 1.0 - 2.0 scale of current zoomlevel
*/ */
public final float scale; public final float scale;
/**
* The hash code of this object. public final float angle;
*/
private transient int hashCodeValue; public final double x;
public final double y;
/** /**
* @param geoPoint * @param geoPoint
@ -51,62 +49,40 @@ public class MapPosition implements Serializable {
* @param scale * @param scale
* ... * ...
*/ */
public MapPosition(GeoPoint geoPoint, byte zoomLevel, float scale) { public MapPosition(GeoPoint geoPoint, byte zoomLevel, float scale) {
this.geoPoint = geoPoint; // this.geoPoint = geoPoint;
this.zoomLevel = zoomLevel; this.zoomLevel = zoomLevel;
this.scale = scale; 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 MapPosition(double latitude, double longitude, byte zoomLevel, float scale,
public boolean equals(Object obj) { float angle) {
if (this == obj) { this.zoomLevel = zoomLevel;
return true; this.scale = scale;
} else if (!(obj instanceof MapPosition)) { this.lat = latitude;
return false; this.lon = longitude;
} this.angle = angle;
MapPosition other = (MapPosition) obj; this.x = MercatorProjection.longitudeToPixelX(longitude, zoomLevel);
if (this.geoPoint == null) { this.y = MercatorProjection.latitudeToPixelY(latitude, zoomLevel);
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;
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("MapPosition [geoPoint="); 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(", zoomLevel=");
builder.append(this.zoomLevel); builder.append(this.zoomLevel);
builder.append("]"); builder.append("]");
return builder.toString(); 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. * @return the ground resolution at the given latitude and zoom level.
*/ */
public static double calculateGroundResolution(double latitude, byte zoomLevel) { 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); * ((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. * 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); 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. * 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); 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. * 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. * the zoom level at which the coordinate should be converted.
* @return the tile X number. * @return the tile X number.
*/ */
public static long pixelXToTileX(double pixelX, byte zoomLevel) { public static int pixelXToTileX(double pixelX, byte zoomLevel) {
return (long) Math.min(Math.max(pixelX / Tile.TILE_SIZE, 0), Math.pow(2, zoomLevel) - 1); 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. * the zoom level at which the coordinate should be converted.
* @return the tile Y number. * @return the tile Y number.
*/ */
public static long pixelYToTileY(double pixelY, byte zoomLevel) { public static int pixelYToTileY(double pixelY, byte zoomLevel) {
return (long) Math.min(Math.max(pixelY / Tile.TILE_SIZE, 0), Math.pow(2, zoomLevel) - 1); 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; public String value;
private transient int hashCodeValue; private transient int hashCodeValue = 0;
/** /**
* @param tag * @param tag
@ -63,7 +63,6 @@ public class Tag {
} }
this.key = tag.substring(0, splitPosition).intern(); this.key = tag.substring(0, splitPosition).intern();
this.value = tag.substring(splitPosition + 1).intern(); this.value = tag.substring(splitPosition + 1).intern();
this.hashCodeValue = calculateHashCode();
} }
public Tag(String tag, boolean hashValue) { public Tag(String tag, boolean hashValue) {
@ -76,8 +75,6 @@ public class Tag {
this.value = tag.substring(splitPosition + 1); this.value = tag.substring(splitPosition + 1);
else else
this.value = tag.substring(splitPosition + 1).intern(); this.value = tag.substring(splitPosition + 1).intern();
this.hashCodeValue = calculateHashCode();
} }
/** /**
@ -89,7 +86,6 @@ public class Tag {
public Tag(String key, String value) { public Tag(String key, String value) {
this.key = (key == null ? null : key.intern()); this.key = (key == null ? null : key.intern());
this.value = (value == null ? null : value.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.key = (key == null ? null : key);
this.value = (value == null ? null : value); this.value = (value == null ? null : value);
} }
this.hashCodeValue = calculateHashCode();
} }
@Override @Override
@ -121,14 +116,17 @@ public class Tag {
} }
Tag other = (Tag) obj; Tag other = (Tag) obj;
if ((this.key != other.key) || (this.value != other.value)) if ((this.key == other.key) && (this.value == other.value))
return false;
return true; return true;
return false;
} }
@Override @Override
public int hashCode() { public int hashCode() {
if (this.hashCodeValue == 0)
this.hashCodeValue = calculateHashCode();
return this.hashCodeValue; 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. * with their zoom level. The actual area that a tile covers on a map depends on the underlying map projection.
*/ */
public class Tile { 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. * Width and height of a map tile in pixel.
*/ */
public static int TILE_SIZE = 256; 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. * The X number of this tile.
*/ */
public final long tileX; public final int tileX;
/** /**
* The Y number of this tile. * The Y number of this tile.
*/ */
public final long tileY; public final int tileY;
/** /**
* The Zoom level of this tile. * The Zoom level of this tile.
*/ */
public final byte zoomLevel; public final byte zoomLevel;
private transient int hashCodeValue;
/** /**
* the pixel X coordinate of the upper left corner of this tile. * the pixel X coordinate of the upper left corner of this tile.
*/ */
@ -70,51 +59,12 @@ public class Tile {
* @param zoomLevel * @param zoomLevel
* the zoom level of the tile. * 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.tileX = tileX;
this.tileY = tileY; this.tileY = tileY;
this.pixelX = this.tileX * TILE_SIZE; this.pixelX = this.tileX * TILE_SIZE;
this.pixelY = this.tileY * TILE_SIZE; this.pixelY = this.tileY * TILE_SIZE;
this.zoomLevel = zoomLevel; 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 @Override
@ -130,14 +80,34 @@ public class Tile {
return stringBuilder.toString(); return stringBuilder.toString();
} }
/** @Override
* @return the hash code of this object. public boolean equals(Object obj) {
*/ if (this == obj)
private int calculateHashCode() { 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; int result = 7;
result = 31 * result + (int) (this.tileX ^ (this.tileX >>> 32)); result = 31 * result + this.tileX;
result = 31 * result + (int) (this.tileY ^ (this.tileY >>> 32)); result = 31 * result + this.tileY;
result = 31 * result + this.zoomLevel; result = 31 * result + this.zoomLevel;
return result; mHash = result;
}
return mHash;
} }
} }

View File

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