- adding MapDatabase backend for our TileStache provider
- fixing some renering bugs on nexus phone and some refactoring and cleanup
This commit is contained in:
parent
c5c952bf14
commit
124624785d
@ -12,14 +12,15 @@
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="10"
|
||||
android:targetSdkVersion="15" />
|
||||
android:targetSdkVersion="16" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/globe2"
|
||||
android:label="@string/application_name"
|
||||
android:theme="@style/Theme.TileMap" >
|
||||
|
||||
<activity android:name="org.mapsforge.app.TileMap" >
|
||||
android:label="@string/application_name"
|
||||
android:theme="@style/Theme.TileMap" >
|
||||
<activity
|
||||
android:name="org.mapsforge.app.TileMap"
|
||||
android:configChanges="orientation|screenSize" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@ -28,6 +29,6 @@
|
||||
</activity>
|
||||
<activity android:name=".preferences.EditPreferences" />
|
||||
<activity android:name=".filepicker.FilePicker" />
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/mainView"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<org.mapsforge.android.MapView
|
||||
android:id="@+id/mapView"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" />
|
||||
|
||||
<ToggleButton
|
||||
android:id="@+id/snapToLocationView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginRight="10dip"
|
||||
android:layout_marginTop="10dip"
|
||||
android:background="@drawable/snap_to_position"
|
||||
android:textOff=""
|
||||
android:textOn=""
|
||||
android:visibility="gone" />
|
||||
|
||||
</RelativeLayout>
|
||||
71
res/menu/options_menu_pre_honeycomb.xml
Normal file
71
res/menu/options_menu_pre_honeycomb.xml
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_position"
|
||||
android:icon="@drawable/ic_menu_mylocation"
|
||||
android:showAsAction="always"
|
||||
android:title="@string/menu_position">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/menu_position_my_location_enable"
|
||||
android:title="@string/menu_position_my_location_enable"/>
|
||||
<item
|
||||
android:id="@+id/menu_position_my_location_disable"
|
||||
android:title="@string/menu_position_my_location_disable"/>
|
||||
<item
|
||||
android:id="@+id/menu_position_last_known"
|
||||
android:title="@string/menu_position_last_known"/>
|
||||
<item
|
||||
android:id="@+id/menu_position_enter_coordinates"
|
||||
android:title="@string/menu_position_enter_coordinates"/>
|
||||
<item
|
||||
android:id="@+id/menu_position_map_center"
|
||||
android:title="@string/menu_position_map_file_center"/>
|
||||
</menu>
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/menu_options"
|
||||
android:icon="@drawable/ic_menu_options"
|
||||
android:showAsAction="always"
|
||||
android:title="@string/menu_options">
|
||||
|
||||
<menu>
|
||||
<!-- android:icon="@drawable/ic_menu_preferences" -->
|
||||
<item
|
||||
android:id="@+id/menu_preferences"
|
||||
|
||||
android:showAsAction="never"
|
||||
android:title="@string/menu_preferences"/>
|
||||
<!-- android:icon="@drawable/ic_menu_mapmode" -->
|
||||
|
||||
<!-- android:icon="@drawable/ic_menu_archive" -->
|
||||
<item
|
||||
android:id="@+id/menu_mapfile"
|
||||
|
||||
android:showAsAction="never"
|
||||
android:title="@string/menu_mapfile"/>
|
||||
<!-- <item
|
||||
android:id="@+id/menu_info_map_file"
|
||||
android:title="@string/menu_info_map_file"/> -->
|
||||
</menu>
|
||||
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_render_theme"
|
||||
|
||||
android:showAsAction="never"
|
||||
android:title="@string/menu_render_theme">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/menu_render_theme_osmarender"
|
||||
android:title="@string/menu_render_theme_osmarender"/>
|
||||
<item
|
||||
android:id="@+id/menu_render_theme_select_file"
|
||||
android:title="@string/menu_render_theme_select_file"/>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
|
||||
</menu>
|
||||
@ -3,6 +3,7 @@
|
||||
<string-array name="preferences_map_generator_values">
|
||||
<item>Mapfile</item>
|
||||
<item>PostGIS</item>
|
||||
<item>OpenScienceMap</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="preferences_scale_bar_unit_values">
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
<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">
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
<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">
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
<string-array name="preferences_map_database_keys">
|
||||
<item>MAP_READER</item>
|
||||
<item>POSTGIS_READER</item>
|
||||
<item>PBMAP_READER</item>
|
||||
</string-array>
|
||||
<string name="preferences_map_database_default">POSTGIS_READER</string>
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
<string-array name="preferences_map_generator_values">
|
||||
<item>Mapfile</item>
|
||||
<item>PostGIS</item>
|
||||
<item>OpenScienceMap</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="preferences_scale_bar_unit_values">
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
*/
|
||||
package org.mapsforge.android;
|
||||
|
||||
import org.mapsforge.android.mapgenerator.IMapGenerator;
|
||||
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
|
||||
|
||||
import android.opengl.GLSurfaceView;
|
||||
@ -21,7 +22,7 @@ import android.opengl.GLSurfaceView;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface MapRenderer extends GLSurfaceView.Renderer {
|
||||
public interface IMapRenderer extends GLSurfaceView.Renderer {
|
||||
|
||||
/**
|
||||
* @param mapGeneratorJob
|
||||
@ -31,9 +32,8 @@ public interface MapRenderer extends GLSurfaceView.Renderer {
|
||||
public boolean passTile(MapGeneratorJob mapGeneratorJob);
|
||||
|
||||
/**
|
||||
* @return true when tile passed to renderer is processed false otherwise.
|
||||
* used to lock overwriting resources passed with the tile
|
||||
* (e.g. lock until bitmap is loaded to texture)
|
||||
* @return true when tile passed to renderer is processed false otherwise. used to lock overwriting resources passed
|
||||
* with the tile (e.g. lock until bitmap is loaded to texture)
|
||||
*/
|
||||
public boolean processedTile();
|
||||
|
||||
@ -44,4 +44,6 @@ public interface MapRenderer extends GLSurfaceView.Renderer {
|
||||
* ...
|
||||
*/
|
||||
public void redrawTiles(boolean clear);
|
||||
|
||||
public IMapGenerator createMapGenerator();
|
||||
}
|
||||
@ -16,25 +16,35 @@ package org.mapsforge.android;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.mapsforge.android.input.TouchHandler;
|
||||
import org.mapsforge.android.mapgenerator.IMapGenerator;
|
||||
import org.mapsforge.android.mapgenerator.JobParameters;
|
||||
import org.mapsforge.android.mapgenerator.JobQueue;
|
||||
import org.mapsforge.android.mapgenerator.JobTheme;
|
||||
import org.mapsforge.android.mapgenerator.MapDatabaseFactory;
|
||||
import org.mapsforge.android.mapgenerator.MapDatabaseInternal;
|
||||
import org.mapsforge.android.mapgenerator.MapGeneratorFactory;
|
||||
import org.mapsforge.android.mapgenerator.MapGeneratorInternal;
|
||||
import org.mapsforge.android.mapgenerator.MapDatabases;
|
||||
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
|
||||
import org.mapsforge.android.mapgenerator.MapRendererFactory;
|
||||
import org.mapsforge.android.mapgenerator.MapRenderers;
|
||||
import org.mapsforge.android.mapgenerator.MapWorker;
|
||||
import org.mapsforge.android.mapgenerator.Theme;
|
||||
import org.mapsforge.android.rendertheme.ExternalRenderTheme;
|
||||
import org.mapsforge.android.rendertheme.InternalRenderTheme;
|
||||
import org.mapsforge.android.rendertheme.RenderTheme;
|
||||
import org.mapsforge.android.rendertheme.RenderThemeHandler;
|
||||
import org.mapsforge.android.utils.GlConfigChooser;
|
||||
import org.mapsforge.core.GeoPoint;
|
||||
import org.mapsforge.core.MapPosition;
|
||||
import org.mapsforge.database.FileOpenResult;
|
||||
import org.mapsforge.database.IMapDatabase;
|
||||
import org.mapsforge.database.MapFileInfo;
|
||||
import org.mapsforge.database.mapfile.MapDatabase;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.opengl.GLSurfaceView;
|
||||
@ -49,8 +59,7 @@ import android.view.MotionEvent;
|
||||
* <p>
|
||||
* This implementation supports offline map rendering as well as downloading map images (tiles) over an Internet
|
||||
* connection. The operation mode of a MapView can be set in the constructor and changed at runtime with the
|
||||
* {@link #setMapGeneratorInternal(IMapGenerator)} method. Some MapView parameters depend on the selected operation
|
||||
* mode.
|
||||
* {@link #setMapDatabase(MapDatabases)} method. Some MapView parameters depend on the selected operation mode.
|
||||
* <p>
|
||||
* In offline rendering mode a special database file is required which contains the map data. Map files can be stored in
|
||||
* any folder. The current map file is set by calling {@link #setMapFile(String)}. To retrieve the current
|
||||
@ -67,12 +76,12 @@ public class MapView extends GLSurfaceView {
|
||||
public static final InternalRenderTheme DEFAULT_RENDER_THEME = InternalRenderTheme.OSMARENDER;
|
||||
|
||||
private static final float DEFAULT_TEXT_SCALE = 1;
|
||||
private static final Byte DEFAULT_START_ZOOM_LEVEL = Byte.valueOf((byte) 16);
|
||||
|
||||
private final MapController mMapController;
|
||||
// private final MapMover mMapMover;
|
||||
// private final ZoomAnimator mZoomAnimator;
|
||||
|
||||
private final MapScaleBar mMapScaleBar;
|
||||
// private final MapScaleBar mMapScaleBar;
|
||||
private final MapViewPosition mMapViewPosition;
|
||||
|
||||
private final MapZoomControls mMapZoomControls;
|
||||
@ -80,10 +89,11 @@ public class MapView extends GLSurfaceView {
|
||||
private final TouchHandler mTouchEventHandler;
|
||||
|
||||
private IMapDatabase mMapDatabase;
|
||||
private IMapGenerator mMapGenerator;
|
||||
private MapRenderer mMapRenderer;
|
||||
private MapDatabases mMapDatabaseType;
|
||||
private IMapRenderer mMapRenderer;
|
||||
private JobQueue mJobQueue;
|
||||
private MapWorker mMapWorker;
|
||||
private MapWorker mMapWorkers[];
|
||||
private int mNumMapWorkers = 6;
|
||||
private JobParameters mJobParameters;
|
||||
private DebugSettings mDebugSettings;
|
||||
private String mMapFile;
|
||||
@ -95,9 +105,7 @@ public class MapView extends GLSurfaceView {
|
||||
* if the context object is not an instance of {@link MapActivity} .
|
||||
*/
|
||||
public MapView(Context context) {
|
||||
this(context, null,
|
||||
MapGeneratorFactory.createMapGenerator(MapGeneratorInternal.GL_RENDERER),
|
||||
MapDatabaseFactory.createMapDatabase(MapDatabaseInternal.MAP_READER));
|
||||
this(context, null, MapRenderers.GL_RENDERER, MapDatabases.MAP_READER);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,25 +118,12 @@ public class MapView extends GLSurfaceView {
|
||||
*/
|
||||
public MapView(Context context, AttributeSet attributeSet) {
|
||||
this(context, attributeSet,
|
||||
MapGeneratorFactory.createMapGenerator(attributeSet),
|
||||
MapDatabaseFactory.createMapDatabase(attributeSet));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* the enclosing MapActivity instance.
|
||||
* @param mapGenerator
|
||||
* the MapGenerator for this MapView.
|
||||
* @throws IllegalArgumentException
|
||||
* if the context object is not an instance of {@link MapActivity} .
|
||||
*/
|
||||
public MapView(Context context, IMapGenerator mapGenerator) {
|
||||
this(context, null, mapGenerator, MapDatabaseFactory
|
||||
.createMapDatabase(MapDatabaseInternal.MAP_READER));
|
||||
MapRendererFactory.getMapGenerator(attributeSet),
|
||||
MapDatabaseFactory.getMapDatabase(attributeSet));
|
||||
}
|
||||
|
||||
private MapView(Context context, AttributeSet attributeSet,
|
||||
IMapGenerator mapGenerator, IMapDatabase mapDatabase) {
|
||||
MapRenderers mapGeneratorType, MapDatabases mapDatabaseType) {
|
||||
|
||||
super(context, attributeSet);
|
||||
|
||||
@ -147,46 +142,63 @@ public class MapView extends GLSurfaceView {
|
||||
mJobParameters = new JobParameters(DEFAULT_RENDER_THEME, DEFAULT_TEXT_SCALE);
|
||||
mMapController = new MapController(this);
|
||||
|
||||
// mMapDatabase = MapDatabaseFactory.createMapDatabase(MapDatabaseInternal.POSTGIS_READER);
|
||||
// mMapDatabase = MapDatabaseFactory.createMapDatabase(MapDatabaseInternal.JSON_READER);
|
||||
mMapDatabase = mapDatabase;
|
||||
mMapDatabaseType = mapDatabaseType;
|
||||
|
||||
mMapViewPosition = new MapViewPosition(this);
|
||||
mMapScaleBar = new MapScaleBar(this);
|
||||
// mMapScaleBar = new MapScaleBar(this);
|
||||
mMapZoomControls = new MapZoomControls(mapActivity, this);
|
||||
mProjection = new MapViewProjection(this);
|
||||
mTouchEventHandler = new TouchHandler(mapActivity, this);
|
||||
|
||||
mJobQueue = new JobQueue(this);
|
||||
mMapWorker = new MapWorker(this);
|
||||
mMapWorker.start();
|
||||
|
||||
// mMapMover = new MapMover(this);
|
||||
// mMapMover.start();
|
||||
// mZoomAnimator = new ZoomAnimator(this);
|
||||
// mZoomAnimator.start();
|
||||
|
||||
setMapGeneratorInternal(mapGenerator);
|
||||
mMapRenderer = MapRendererFactory.createMapRenderer(this, mapGeneratorType);
|
||||
mMapWorkers = new MapWorker[mNumMapWorkers];
|
||||
|
||||
GeoPoint startPoint = mMapGenerator.getStartPoint();
|
||||
if (startPoint != null) {
|
||||
mMapViewPosition.setMapCenter(startPoint);
|
||||
for (int i = 0; i < mNumMapWorkers; i++) {
|
||||
IMapDatabase mapDatabase = MapDatabaseFactory
|
||||
.createMapDatabase(mapDatabaseType);
|
||||
|
||||
IMapGenerator mapGenerator = mMapRenderer.createMapGenerator();
|
||||
mapGenerator.setMapDatabase(mapDatabase);
|
||||
|
||||
if (i == 0) {
|
||||
mMapDatabase = mapDatabase;
|
||||
initMapStartPosition();
|
||||
|
||||
// mapGenerator.setRendertheme(DEFAULT_RENDER_THEME);
|
||||
}
|
||||
mMapWorkers[i] = new MapWorker(i, this, mapGenerator, mMapRenderer);
|
||||
mMapWorkers[i].start();
|
||||
}
|
||||
|
||||
Byte startZoomLevel = mMapGenerator.getStartZoomLevel();
|
||||
if (startZoomLevel != null) {
|
||||
mMapViewPosition.setZoomLevel(startZoomLevel.byteValue());
|
||||
}
|
||||
setRenderTheme(InternalRenderTheme.OSMARENDER);
|
||||
|
||||
mapActivity.registerMapView(this);
|
||||
|
||||
setEGLConfigChooser(new GlConfigChooser());
|
||||
setEGLContextClientVersion(2);
|
||||
|
||||
mMapRenderer = mMapGenerator.getMapRenderer(this);
|
||||
setRenderer(mMapRenderer);
|
||||
|
||||
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
|
||||
mMapWorker.setMapRenderer(mMapRenderer);
|
||||
}
|
||||
|
||||
private void initMapStartPosition() {
|
||||
GeoPoint startPoint = getStartPoint();
|
||||
if (startPoint != null) {
|
||||
mMapViewPosition.setMapCenter(startPoint);
|
||||
}
|
||||
|
||||
Byte startZoomLevel = getStartZoomLevel();
|
||||
if (startZoomLevel != null) {
|
||||
mMapViewPosition.setZoomLevel(startZoomLevel.byteValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -224,13 +236,6 @@ public class MapView extends GLSurfaceView {
|
||||
return mMapFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the currently used MapGenerator (may be null).
|
||||
*/
|
||||
public IMapGenerator getMapGenerator() {
|
||||
return mMapGenerator;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return the MapMover which is used by this MapView.
|
||||
// */
|
||||
@ -245,19 +250,19 @@ public class MapView extends GLSurfaceView {
|
||||
return mMapViewPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the scale bar which is used in this MapView.
|
||||
*/
|
||||
public MapScaleBar getMapScaleBar() {
|
||||
return mMapScaleBar;
|
||||
}
|
||||
// /**
|
||||
// * @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 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.
|
||||
@ -362,37 +367,41 @@ public class MapView extends GLSurfaceView {
|
||||
|
||||
// mZoomAnimator.pause();
|
||||
// mMapMover.pause();
|
||||
mMapWorker.pause();
|
||||
// mZoomAnimator.awaitPausing();
|
||||
// mMapMover.awaitPausing();
|
||||
mMapWorker.awaitPausing();
|
||||
// mZoomAnimator.proceed();
|
||||
// mMapMover.stopMove();
|
||||
// mMapMover.proceed();
|
||||
mMapWorker.proceed();
|
||||
|
||||
mMapDatabase.closeFile();
|
||||
boolean initialized = false;
|
||||
|
||||
if (mapFile != null)
|
||||
fileOpenResult = mMapDatabase.openFile(new File(mapFile));
|
||||
else
|
||||
fileOpenResult = mMapDatabase.openFile(null);
|
||||
mJobQueue.clear();
|
||||
|
||||
if (fileOpenResult != null && fileOpenResult.isSuccess()) {
|
||||
mMapFile = mapFile;
|
||||
mapWorkersPause();
|
||||
|
||||
GeoPoint startPoint = mMapGenerator.getStartPoint();
|
||||
if (startPoint != null) {
|
||||
Log.d(TAG, "mapfile got startpoint");
|
||||
mMapViewPosition.setMapCenter(startPoint);
|
||||
for (MapWorker mapWorker : mMapWorkers) {
|
||||
|
||||
IMapGenerator mapGenerator = mapWorker.getMapGenerator();
|
||||
IMapDatabase mapDatabase = mapGenerator.getMapDatabase();
|
||||
|
||||
mapDatabase.closeFile();
|
||||
|
||||
if (mapFile != null)
|
||||
fileOpenResult = mapDatabase.openFile(new File(mapFile));
|
||||
else
|
||||
fileOpenResult = mapDatabase.openFile(null);
|
||||
|
||||
if (fileOpenResult != null && fileOpenResult.isSuccess()) {
|
||||
mMapFile = mapFile;
|
||||
|
||||
if (!initialized)
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
Byte startZoomLevel = mMapGenerator.getStartZoomLevel();
|
||||
if (startZoomLevel != null) {
|
||||
Log.d(TAG, "mapfile got start zoomlevel");
|
||||
mMapViewPosition.setZoomLevel(startZoomLevel.byteValue());
|
||||
}
|
||||
mapWorkersProceed();
|
||||
|
||||
if (initialized) {
|
||||
clearAndRedrawMapView();
|
||||
Log.d(TAG, "mapfile set");
|
||||
return true;
|
||||
@ -404,76 +413,61 @@ public class MapView extends GLSurfaceView {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the MapGenerator for this MapView.
|
||||
*
|
||||
* @param mapGenerator
|
||||
* the new MapGenerator.
|
||||
*/
|
||||
public void setMapGenerator(IMapGenerator mapGenerator) {
|
||||
|
||||
if (mMapGenerator != mapGenerator) {
|
||||
setMapGeneratorInternal(mapGenerator);
|
||||
|
||||
clearAndRedrawMapView();
|
||||
private GeoPoint getStartPoint() {
|
||||
if (mMapDatabase != null && mMapDatabase.hasOpenFile()) {
|
||||
MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo();
|
||||
if (mapFileInfo.startPosition != null) {
|
||||
return mapFileInfo.startPosition;
|
||||
} else if (mapFileInfo.mapCenter != null) {
|
||||
return mapFileInfo.mapCenter;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setMapGeneratorInternal(IMapGenerator mapGenerator) {
|
||||
if (mapGenerator == null) {
|
||||
throw new IllegalArgumentException("mapGenerator must not be null");
|
||||
private Byte getStartZoomLevel() {
|
||||
if (mMapDatabase != null && mMapDatabase.hasOpenFile()) {
|
||||
MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo();
|
||||
if (mapFileInfo.startZoomLevel != null) {
|
||||
return mapFileInfo.startZoomLevel;
|
||||
}
|
||||
}
|
||||
|
||||
mapGenerator.setMapDatabase(mMapDatabase);
|
||||
|
||||
mMapGenerator = mapGenerator;
|
||||
mMapWorker.setMapGenerator(mMapGenerator);
|
||||
|
||||
return DEFAULT_START_ZOOM_LEVEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the MapDatabase for this MapView.
|
||||
*
|
||||
* @param mapDatabase
|
||||
* @param mapDatabaseType
|
||||
* the new MapDatabase.
|
||||
*/
|
||||
public void setMapDatabase(IMapDatabase mapDatabase) {
|
||||
Log.d(TAG, "setMapDatabase " + mapDatabase.getClass());
|
||||
if (mMapDatabase != mapDatabase) {
|
||||
|
||||
if (mMapDatabase != null)
|
||||
mMapDatabase.closeFile();
|
||||
public void setMapDatabase(MapDatabases mapDatabaseType) {
|
||||
IMapGenerator mapGenerator;
|
||||
|
||||
setMapDatabaseInternal(mapDatabase);
|
||||
Log.d(TAG, "setMapDatabase " + mapDatabaseType.name());
|
||||
|
||||
// clearAndRedrawMapView();
|
||||
}
|
||||
}
|
||||
if (mMapDatabaseType == mapDatabaseType)
|
||||
return;
|
||||
|
||||
private void setMapDatabaseInternal(IMapDatabase mapDatabase) {
|
||||
if (mapDatabase == null) {
|
||||
throw new IllegalArgumentException("MapDatabase must not be null");
|
||||
}
|
||||
mapWorkersPause();
|
||||
|
||||
if (!mMapWorker.isPausing()) {
|
||||
mMapWorker.pause();
|
||||
mMapWorker.awaitPausing();
|
||||
for (MapWorker mapWorker : mMapWorkers) {
|
||||
mapGenerator = mapWorker.getMapGenerator();
|
||||
|
||||
mapGenerator.setMapDatabase(MapDatabaseFactory
|
||||
.createMapDatabase(mapDatabaseType));
|
||||
}
|
||||
|
||||
mJobQueue.clear();
|
||||
mMapDatabase = mapDatabase;
|
||||
mMapGenerator.setMapDatabase(mMapDatabase);
|
||||
|
||||
Log.d(TAG, "setMapDatabaseInternal " + mapDatabase.getClass());
|
||||
|
||||
String mapFile = mMapFile;
|
||||
mMapFile = null;
|
||||
setMapFile(mapFile);
|
||||
|
||||
mMapWorker.proceed();
|
||||
|
||||
// mMapWorker.setMapDatabase(mMapDatabase);
|
||||
|
||||
mapWorkersProceed();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -489,8 +483,7 @@ public class MapView extends GLSurfaceView {
|
||||
throw new IllegalArgumentException("render theme must not be null");
|
||||
}
|
||||
|
||||
Log.d(TAG, "set rendertheme " + internalRenderTheme);
|
||||
mJobParameters = new JobParameters(internalRenderTheme, mJobParameters.textScale);
|
||||
setRenderTheme((Theme) internalRenderTheme);
|
||||
|
||||
clearAndRedrawMapView();
|
||||
}
|
||||
@ -510,12 +503,40 @@ public class MapView extends GLSurfaceView {
|
||||
throw new IllegalArgumentException("render theme path must not be null");
|
||||
}
|
||||
|
||||
JobTheme jobTheme = new ExternalRenderTheme(renderThemePath);
|
||||
mJobParameters = new JobParameters(jobTheme, mJobParameters.textScale);
|
||||
setRenderTheme(new ExternalRenderTheme(renderThemePath));
|
||||
|
||||
clearAndRedrawMapView();
|
||||
}
|
||||
|
||||
private boolean setRenderTheme(Theme theme) {
|
||||
|
||||
mapWorkersPause();
|
||||
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = theme.getRenderThemeAsStream();
|
||||
RenderTheme t = RenderThemeHandler.getRenderTheme(inputStream);
|
||||
mMapWorkers[0].getMapGenerator().setRenderTheme(t);
|
||||
return true;
|
||||
} catch (ParserConfigurationException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} catch (SAXException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} finally {
|
||||
mapWorkersProceed();
|
||||
try {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text scale for the map rendering. Has no effect in downloading mode.
|
||||
*
|
||||
@ -523,7 +544,7 @@ public class MapView extends GLSurfaceView {
|
||||
* the new text scale for the map rendering.
|
||||
*/
|
||||
public void setTextScale(float textScale) {
|
||||
mJobParameters = new JobParameters(mJobParameters.jobTheme, textScale);
|
||||
mJobParameters = new JobParameters(mJobParameters.theme, textScale);
|
||||
clearAndRedrawMapView();
|
||||
}
|
||||
|
||||
@ -583,28 +604,33 @@ public class MapView extends GLSurfaceView {
|
||||
@Override
|
||||
protected synchronized void onSizeChanged(int width, int height, int oldWidth,
|
||||
int oldHeight) {
|
||||
mMapWorker.pause();
|
||||
mMapWorker.awaitPausing();
|
||||
super.onSizeChanged(width, height, oldWidth, oldHeight);
|
||||
mMapWorker.proceed();
|
||||
|
||||
for (MapWorker mapWorker : mMapWorkers) {
|
||||
mapWorker.pause();
|
||||
mapWorker.awaitPausing();
|
||||
super.onSizeChanged(width, height, oldWidth, oldHeight);
|
||||
mapWorker.proceed();
|
||||
}
|
||||
// redrawTiles();
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
// mMapMover.interrupt();
|
||||
mMapWorker.interrupt();
|
||||
// mZoomAnimator.interrupt();
|
||||
|
||||
try {
|
||||
mMapWorker.join();
|
||||
} catch (InterruptedException e) {
|
||||
// restore the interrupted status
|
||||
Thread.currentThread().interrupt();
|
||||
for (MapWorker mapWorker : mMapWorkers) {
|
||||
mapWorker.interrupt();
|
||||
|
||||
try {
|
||||
mapWorker.join();
|
||||
} catch (InterruptedException e) {
|
||||
// restore the interrupted status
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
IMapDatabase mapDatabase = mapWorker.getMapGenerator().getMapDatabase();
|
||||
mapDatabase.closeFile();
|
||||
}
|
||||
|
||||
mMapScaleBar.destroy();
|
||||
mMapDatabase.closeFile();
|
||||
// mMapScaleBar.destroy();
|
||||
|
||||
}
|
||||
|
||||
@ -612,8 +638,9 @@ public class MapView extends GLSurfaceView {
|
||||
* @return the maximum possible zoom level.
|
||||
*/
|
||||
byte getMaximumPossibleZoomLevel() {
|
||||
return (byte) Math.min(mMapZoomControls.getZoomLevelMax(),
|
||||
mMapGenerator.getZoomLevelMax());
|
||||
return (byte) 20;
|
||||
// FIXME Math.min(mMapZoomControls.getZoomLevelMax(),
|
||||
// mMapGenerator.getZoomLevelMax());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -639,7 +666,9 @@ public class MapView extends GLSurfaceView {
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mMapWorker.pause();
|
||||
for (MapWorker mapWorker : mMapWorkers)
|
||||
mapWorker.pause();
|
||||
|
||||
// mMapMover.pause();
|
||||
// mZoomAnimator.pause();
|
||||
}
|
||||
@ -647,7 +676,9 @@ public class MapView extends GLSurfaceView {
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mMapWorker.proceed();
|
||||
for (MapWorker mapWorker : mMapWorkers)
|
||||
mapWorker.proceed();
|
||||
|
||||
// mMapMover.proceed();
|
||||
// mZoomAnimator.proceed();
|
||||
}
|
||||
@ -706,9 +737,33 @@ public class MapView extends GLSurfaceView {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MapWorker
|
||||
* add jobs and remember MapWorkers that stuff needs to be done
|
||||
*
|
||||
* @param jobs
|
||||
* tile jobs
|
||||
*/
|
||||
public MapWorker getMapWorker() {
|
||||
return mMapWorker;
|
||||
public void addJobs(ArrayList<MapGeneratorJob> jobs) {
|
||||
mJobQueue.setJobs(jobs);
|
||||
|
||||
for (MapWorker m : mMapWorkers) {
|
||||
synchronized (m) {
|
||||
m.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mapWorkersPause() {
|
||||
for (MapWorker mapWorker : mMapWorkers) {
|
||||
if (!mapWorker.isPausing()) {
|
||||
mapWorker.pause();
|
||||
mapWorker.awaitPausing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mapWorkersProceed() {
|
||||
for (MapWorker mapWorker : mMapWorkers)
|
||||
mapWorker.proceed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ import android.util.FloatMath;
|
||||
public class MapViewPosition {
|
||||
private static float MAX_SCALE = 2.0f;
|
||||
private static float MIN_SCALE = 1.0f;
|
||||
private static int MAX_ZOOMLEVEL = 16;
|
||||
|
||||
private double mLatitude;
|
||||
private double mLongitude;
|
||||
@ -162,12 +163,14 @@ public class MapViewPosition {
|
||||
float s = mScale * scale;
|
||||
|
||||
if (s >= MAX_SCALE) {
|
||||
|
||||
byte z = (byte) FloatMath.sqrt(s);
|
||||
if (z != 0 && mZoomLevel == 20)
|
||||
if (s > 8)
|
||||
return;
|
||||
mZoomLevel += z;
|
||||
s *= 1.0f / (1 << z);
|
||||
|
||||
if (mZoomLevel <= MAX_ZOOMLEVEL) {
|
||||
byte z = (byte) FloatMath.sqrt(s);
|
||||
mZoomLevel += z;
|
||||
s *= 1.0f / (1 << z);
|
||||
}
|
||||
} else if (s < MIN_SCALE) {
|
||||
byte z = (byte) FloatMath.sqrt(1 / s);
|
||||
if (z != 0 && mZoomLevel == 1)
|
||||
|
||||
@ -18,31 +18,33 @@ package org.mapsforge.android.glrenderer;
|
||||
import java.util.LinkedList;
|
||||
|
||||
class LayerPool {
|
||||
static private LinkedList<PoolItem> pool;
|
||||
static private LinkedList<PoolItem> pool = null;
|
||||
static private int count;
|
||||
|
||||
static void init() {
|
||||
pool = new LinkedList<PoolItem>();
|
||||
count = 0;
|
||||
if (pool == null) {
|
||||
pool = new LinkedList<PoolItem>();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static PoolItem get() {
|
||||
if (count == 0)
|
||||
return new PoolItem();
|
||||
|
||||
PoolItem it;
|
||||
synchronized (pool) {
|
||||
count--;
|
||||
it = pool.pop();
|
||||
it.used = 0;
|
||||
}
|
||||
|
||||
return it;
|
||||
if (count == 0)
|
||||
return new PoolItem();
|
||||
|
||||
count--;
|
||||
PoolItem it = pool.pop();
|
||||
it.used = 0;
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
static void add(LinkedList<PoolItem> items) {
|
||||
int size = items.size();
|
||||
synchronized (pool) {
|
||||
int size = items.size();
|
||||
|
||||
while (count < 4096 && size-- > 0) {
|
||||
count++;
|
||||
pool.add(items.pop());
|
||||
|
||||
@ -61,7 +61,7 @@ class LineLayers {
|
||||
ByteOrder.nativeOrder());
|
||||
fbuf = bbuf.asFloatBuffer();
|
||||
} else {
|
||||
fbuf.position(0);
|
||||
fbuf.clear();
|
||||
}
|
||||
int pos = 0;
|
||||
|
||||
@ -81,7 +81,7 @@ class LineLayers {
|
||||
l.pool = null;
|
||||
}
|
||||
|
||||
fbuf.position(0);
|
||||
fbuf.flip();
|
||||
|
||||
// not needed for drawing
|
||||
layers = null;
|
||||
@ -105,7 +105,7 @@ class LineLayers {
|
||||
ByteOrder.nativeOrder());
|
||||
sbuf = bbuf.asShortBuffer();
|
||||
} else {
|
||||
sbuf.position(0);
|
||||
sbuf.clear();
|
||||
}
|
||||
int pos = 0;
|
||||
|
||||
@ -129,7 +129,7 @@ class LineLayers {
|
||||
l.pool = null;
|
||||
}
|
||||
|
||||
sbuf.position(0);
|
||||
sbuf.flip();
|
||||
|
||||
// not needed for drawing
|
||||
layers = null;
|
||||
|
||||
@ -14,29 +14,19 @@
|
||||
*/
|
||||
package org.mapsforge.android.glrenderer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.mapsforge.android.MapView;
|
||||
import org.mapsforge.android.mapgenerator.IMapGenerator;
|
||||
import org.mapsforge.android.mapgenerator.JobTheme;
|
||||
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
|
||||
import org.mapsforge.android.rendertheme.IRenderCallback;
|
||||
import org.mapsforge.android.rendertheme.RenderTheme;
|
||||
import org.mapsforge.android.rendertheme.RenderThemeHandler;
|
||||
import org.mapsforge.android.rendertheme.renderinstruction.Area;
|
||||
import org.mapsforge.android.rendertheme.renderinstruction.Line;
|
||||
import org.mapsforge.core.GeoPoint;
|
||||
import org.mapsforge.core.WebMercator;
|
||||
import org.mapsforge.android.rendertheme.renderinstruction.RenderInstruction;
|
||||
import org.mapsforge.core.MercatorProjection;
|
||||
import org.mapsforge.core.Tag;
|
||||
import org.mapsforge.core.Tile;
|
||||
import org.mapsforge.core.WebMercator;
|
||||
import org.mapsforge.database.IMapDatabase;
|
||||
import org.mapsforge.database.IMapDatabaseCallback;
|
||||
import org.mapsforge.database.MapFileInfo;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
@ -46,33 +36,26 @@ import android.util.Log;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
IMapDatabaseCallback {
|
||||
private static String TAG = DatabaseRenderer.class.getName();
|
||||
public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabaseCallback {
|
||||
|
||||
private static String TAG = MapGenerator.class.getName();
|
||||
|
||||
private static final byte ZOOM_MAX = 22;
|
||||
private static final Byte DEFAULT_START_ZOOM_LEVEL = Byte.valueOf((byte) 16);
|
||||
private static final double PI180 = (Math.PI / 180) / 1000000.0;
|
||||
private static final double PIx4 = Math.PI * 4;
|
||||
private static final double STROKE_INCREASE = Math.sqrt(2);
|
||||
private static final byte STROKE_MIN_ZOOM_LEVEL = 12;
|
||||
private static final byte LAYERS = 11;
|
||||
private static final double f900913 = 20037508.342789244;
|
||||
|
||||
private static RenderTheme renderTheme;
|
||||
|
||||
private IMapDatabase mMapDatabase;
|
||||
|
||||
private JobTheme mPreviousJobTheme;
|
||||
// private float mPreviousTextScale;
|
||||
private byte mPreviousZoomLevel;
|
||||
|
||||
private GLMapTile mCurrentTile;
|
||||
|
||||
private float[] mWayNodes;
|
||||
private int[] mWays;
|
||||
|
||||
private ArrayList<float[]> mCurrentLines;
|
||||
|
||||
private LineLayers mLineLayers;
|
||||
private PolygonLayers mPolyLayers;
|
||||
private MeshLayers mMeshLayers;
|
||||
@ -81,14 +64,13 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
private int mLevels;
|
||||
|
||||
private boolean useSphericalMercator = false;
|
||||
private float mStrokeScale = 1.0f;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public DatabaseRenderer() {
|
||||
public MapGenerator() {
|
||||
Log.d(TAG, "init DatabaseRenderer");
|
||||
mCurrentLines = new ArrayList<float[]>();
|
||||
|
||||
LayerPool.init();
|
||||
}
|
||||
|
||||
@ -107,7 +89,6 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
private boolean mProjected;
|
||||
private boolean mProjectedResult;
|
||||
private float mSimplify;
|
||||
private static final double f900913 = 20037508.342789244;
|
||||
|
||||
private boolean projectToTile(boolean area) {
|
||||
if (mProjected)
|
||||
@ -136,6 +117,8 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
|
||||
for (int pos = 0, outPos = 0, i = 0, m = mWays.length; i < m; i++) {
|
||||
int len = mWays[i];
|
||||
if (len == 0)
|
||||
continue;
|
||||
int cnt = 0;
|
||||
float lat, lon, prevLon = 0, prevLat = 0;
|
||||
|
||||
@ -197,6 +180,8 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
private boolean firstMatch;
|
||||
private boolean prevClosed;
|
||||
|
||||
private RenderInstruction[] mRenderInstructions = null;
|
||||
|
||||
@Override
|
||||
public void renderWay(byte layer, Tag[] tags, float[] wayNodes, int[] wayLength,
|
||||
boolean changed) {
|
||||
@ -220,17 +205,20 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
mSimplify = 0;
|
||||
}
|
||||
|
||||
mCurrentLines.clear();
|
||||
mWayNodes = wayNodes;
|
||||
mWays = wayLength;
|
||||
|
||||
if (!firstMatch && prevClosed == closed && !changed) {
|
||||
DatabaseRenderer.renderTheme.matchWay(this, tags,
|
||||
(byte) (mCurrentTile.zoomLevel + 0),
|
||||
closed, false);
|
||||
if (mRenderInstructions != null) {
|
||||
for (int i = 0, n = mRenderInstructions.length; i < n; i++)
|
||||
mRenderInstructions[i].renderWay(this, tags);
|
||||
}
|
||||
// MapGenerator.renderTheme.matchWay(this, tags,
|
||||
// (byte) (mCurrentTile.zoomLevel + 0),
|
||||
// closed, false);
|
||||
} else {
|
||||
prevClosed = closed;
|
||||
DatabaseRenderer.renderTheme.matchWay(this, tags,
|
||||
mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags,
|
||||
(byte) (mCurrentTile.zoomLevel + 0),
|
||||
closed, true);
|
||||
}
|
||||
@ -273,9 +261,6 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
@Override
|
||||
public void renderWay(Line line) {
|
||||
|
||||
// if (prevClosed && !mProjected)
|
||||
// return;
|
||||
|
||||
projectToTile(false);
|
||||
|
||||
LineLayer outlineLayer = null;
|
||||
@ -284,11 +269,12 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
|
||||
float w = line.strokeWidth;
|
||||
|
||||
if (!line.fixed)
|
||||
w *= mStrokeScale / 1.5f;
|
||||
|
||||
if (!line.fixed) {
|
||||
w *= mStrokeScale;
|
||||
w *= mProjectionScaleFactor;
|
||||
}
|
||||
if (line.outline != -1) {
|
||||
Line outline = DatabaseRenderer.renderTheme.getOutline(line.outline);
|
||||
Line outline = MapGenerator.renderTheme.getOutline(line.outline);
|
||||
if (outline != null) {
|
||||
outlineLayer = mLineLayers.getLayer(mDrawingLayer + outline.level,
|
||||
outline.color, true, false);
|
||||
@ -363,33 +349,19 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
if (mMapDatabase == null)
|
||||
return false;
|
||||
|
||||
useSphericalMercator = WebMercator.NAME.equals(mMapDatabase.getMapProjection());
|
||||
|
||||
mCurrentTile = (GLMapTile) mapGeneratorJob.tile;
|
||||
mDebugDrawPolygons = !mapGeneratorJob.debugSettings.mDisablePolygons;
|
||||
|
||||
// FIXME still chance of concurrency with maprenderer updateVisibleList ?
|
||||
if (mCurrentTile.isLoading || mCurrentTile.isDrawn)
|
||||
return false;
|
||||
|
||||
mCurrentTile.isLoading = true;
|
||||
|
||||
JobTheme jobTheme = mapGeneratorJob.jobParameters.jobTheme;
|
||||
mLevels = MapGenerator.renderTheme.getLevels();
|
||||
|
||||
if (jobTheme != mPreviousJobTheme) {
|
||||
if (!setRenderTheme(jobTheme)) {
|
||||
mPreviousJobTheme = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
mPreviousJobTheme = jobTheme;
|
||||
mPreviousZoomLevel = Byte.MIN_VALUE;
|
||||
mLevels = DatabaseRenderer.renderTheme.getLevels();
|
||||
}
|
||||
|
||||
byte zoomLevel = mCurrentTile.zoomLevel;
|
||||
if (zoomLevel != mPreviousZoomLevel) {
|
||||
setScaleStrokeWidth(zoomLevel);
|
||||
mPreviousZoomLevel = zoomLevel;
|
||||
}
|
||||
setScaleStrokeWidth(mCurrentTile.zoomLevel);
|
||||
|
||||
mLineLayers = new LineLayers();
|
||||
mPolyLayers = new PolygonLayers();
|
||||
@ -399,81 +371,32 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
mCurrentTile.meshLayers = mMeshLayers;
|
||||
|
||||
firstMatch = true;
|
||||
mMapDatabase.executeQuery(mCurrentTile, this);
|
||||
|
||||
// Log.d(TAG, "loaded " + mCurrentTile);
|
||||
mProjectionScaleFactor = (float) (1.0 / Math.cos(MercatorProjection
|
||||
.pixelYToLatitude(mCurrentTile.pixelY, mCurrentTile.zoomLevel)
|
||||
* (Math.PI / 180))) / 1.5f;
|
||||
mMapDatabase.executeQuery(mCurrentTile, this);
|
||||
|
||||
if (mapGeneratorJob.debugSettings.mDrawTileFrames) {
|
||||
float[] coords = { 0, 0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE,
|
||||
Tile.TILE_SIZE, 0, 0, 0 };
|
||||
LineLayer ll = mLineLayers.getLayer(Integer.MAX_VALUE, Color.BLACK, false,
|
||||
true);
|
||||
ll.addLine(coords, 0, coords.length, 1.0f, false);
|
||||
ll.addLine(coords, 0, coords.length, 2.0f, false);
|
||||
}
|
||||
|
||||
mCurrentTile.newData = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeoPoint getStartPoint() {
|
||||
useSphericalMercator = false;
|
||||
|
||||
if (mMapDatabase != null && mMapDatabase.hasOpenFile()) {
|
||||
MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo();
|
||||
|
||||
if (WebMercator.NAME.equals(mapFileInfo.projectionName)) {
|
||||
Log.d(TAG, "using Spherical Mercator");
|
||||
|
||||
useSphericalMercator = true;
|
||||
}
|
||||
if (mapFileInfo.startPosition != null) {
|
||||
return mapFileInfo.startPosition;
|
||||
} else if (mapFileInfo.mapCenter != null) {
|
||||
return mapFileInfo.mapCenter;
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte getStartZoomLevel() {
|
||||
return DEFAULT_START_ZOOM_LEVEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getZoomLevelMax() {
|
||||
return ZOOM_MAX;
|
||||
}
|
||||
|
||||
private static boolean setRenderTheme(JobTheme jobTheme) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = jobTheme.getRenderThemeAsStream();
|
||||
DatabaseRenderer.renderTheme = RenderThemeHandler.getRenderTheme(inputStream);
|
||||
return true;
|
||||
} catch (ParserConfigurationException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} catch (SAXException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private float mProjectionScaleFactor;
|
||||
|
||||
private static byte getValidLayer(byte layer) {
|
||||
if (layer < 0) {
|
||||
return 0;
|
||||
/**
|
||||
* return instances of MapRenderer
|
||||
*/
|
||||
} else if (layer >= LAYERS) {
|
||||
return LAYERS - 1;
|
||||
} else {
|
||||
@ -481,9 +404,17 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapRenderer getMapRenderer(MapView mapView) {
|
||||
return new MapRenderer(mapView);
|
||||
/**
|
||||
* Sets the scale stroke factor for the given zoom level.
|
||||
*
|
||||
* @param zoomLevel
|
||||
* the zoom level for which the scale stroke factor should be set.
|
||||
*/
|
||||
private void setScaleStrokeWidth(byte zoomLevel) {
|
||||
int zoomLevelDiff = Math.max(zoomLevel - STROKE_MIN_ZOOM_LEVEL, 0);
|
||||
mStrokeScale = (float) Math.pow(STROKE_INCREASE, zoomLevelDiff);
|
||||
if (mStrokeScale < 1)
|
||||
mStrokeScale = 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -491,19 +422,13 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
mMapDatabase = mapDatabase;
|
||||
}
|
||||
|
||||
private static float mStrokeScale = 1.0f;
|
||||
@Override
|
||||
public IMapDatabase getMapDatabase() {
|
||||
return mMapDatabase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scale stroke factor for the given zoom level.
|
||||
*
|
||||
* @param zoomLevel
|
||||
* the zoom level for which the scale stroke factor should be set.
|
||||
*/
|
||||
private static void setScaleStrokeWidth(byte zoomLevel) {
|
||||
int zoomLevelDiff = Math.max(zoomLevel - STROKE_MIN_ZOOM_LEVEL, 0);
|
||||
mStrokeScale = (float) Math.pow(STROKE_INCREASE, zoomLevelDiff);
|
||||
if (mStrokeScale < 1)
|
||||
mStrokeScale = 1;
|
||||
// DatabaseRenderer.renderTheme.scaleStrokeWidth(mStrokeScale);
|
||||
@Override
|
||||
public void setRenderTheme(RenderTheme theme) {
|
||||
MapGenerator.renderTheme = theme;
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,57 @@
|
||||
*/
|
||||
package org.mapsforge.android.glrenderer;
|
||||
|
||||
import static android.opengl.GLES20.GL_ARRAY_BUFFER;
|
||||
import static android.opengl.GLES20.GL_BLEND;
|
||||
import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
|
||||
import static android.opengl.GLES20.GL_DEPTH_TEST;
|
||||
import static android.opengl.GLES20.GL_DITHER;
|
||||
import static android.opengl.GLES20.GL_DYNAMIC_DRAW;
|
||||
import static android.opengl.GLES20.GL_EQUAL;
|
||||
import static android.opengl.GLES20.GL_EXTENSIONS;
|
||||
import static android.opengl.GLES20.GL_FLOAT;
|
||||
import static android.opengl.GLES20.GL_INVERT;
|
||||
import static android.opengl.GLES20.GL_NEVER;
|
||||
import static android.opengl.GLES20.GL_ONE_MINUS_SRC_ALPHA;
|
||||
import static android.opengl.GLES20.GL_SCISSOR_TEST;
|
||||
import static android.opengl.GLES20.GL_SRC_ALPHA;
|
||||
import static android.opengl.GLES20.GL_STENCIL_BUFFER_BIT;
|
||||
import static android.opengl.GLES20.GL_STENCIL_TEST;
|
||||
import static android.opengl.GLES20.GL_TRIANGLES;
|
||||
import static android.opengl.GLES20.GL_TRIANGLE_FAN;
|
||||
import static android.opengl.GLES20.GL_TRIANGLE_STRIP;
|
||||
import static android.opengl.GLES20.GL_ZERO;
|
||||
import static android.opengl.GLES20.glBindBuffer;
|
||||
import static android.opengl.GLES20.glBlendFunc;
|
||||
import static android.opengl.GLES20.glBufferData;
|
||||
import static android.opengl.GLES20.glClear;
|
||||
import static android.opengl.GLES20.glClearColor;
|
||||
import static android.opengl.GLES20.glClearStencil;
|
||||
import static android.opengl.GLES20.glColorMask;
|
||||
import static android.opengl.GLES20.glDepthMask;
|
||||
import static android.opengl.GLES20.glDisable;
|
||||
import static android.opengl.GLES20.glDisableVertexAttribArray;
|
||||
import static android.opengl.GLES20.glDrawArrays;
|
||||
import static android.opengl.GLES20.glEnable;
|
||||
import static android.opengl.GLES20.glEnableVertexAttribArray;
|
||||
import static android.opengl.GLES20.glFinish;
|
||||
import static android.opengl.GLES20.glGenBuffers;
|
||||
import static android.opengl.GLES20.glGetAttribLocation;
|
||||
import static android.opengl.GLES20.glGetString;
|
||||
import static android.opengl.GLES20.glGetUniformLocation;
|
||||
import static android.opengl.GLES20.glScissor;
|
||||
import static android.opengl.GLES20.glStencilFunc;
|
||||
import static android.opengl.GLES20.glStencilMask;
|
||||
import static android.opengl.GLES20.glStencilOp;
|
||||
import static android.opengl.GLES20.glUniform1f;
|
||||
import static android.opengl.GLES20.glUniform2f;
|
||||
import static android.opengl.GLES20.glUniform4f;
|
||||
import static android.opengl.GLES20.glUniform4fv;
|
||||
import static android.opengl.GLES20.glUniformMatrix4fv;
|
||||
import static android.opengl.GLES20.glUseProgram;
|
||||
import static android.opengl.GLES20.glVertexAttribPointer;
|
||||
import static android.opengl.GLES20.glViewport;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
import java.util.ArrayList;
|
||||
@ -25,10 +76,9 @@ import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import org.mapsforge.android.DebugSettings;
|
||||
import org.mapsforge.android.MapView;
|
||||
import org.mapsforge.android.mapgenerator.JobParameters;
|
||||
import org.mapsforge.android.mapgenerator.IMapGenerator;
|
||||
import org.mapsforge.android.mapgenerator.JobParameters;
|
||||
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
|
||||
import org.mapsforge.android.mapgenerator.MapWorker;
|
||||
import org.mapsforge.android.mapgenerator.TileCacheKey;
|
||||
import org.mapsforge.android.mapgenerator.TileDistanceSort;
|
||||
import org.mapsforge.android.utils.GlConfigChooser;
|
||||
@ -47,12 +97,15 @@ import android.util.Log;
|
||||
* TODO - use proxy child/parent tile nearer to current tile (currently it is always parent first) - use stencil instead
|
||||
* of scissor mask for rotation - draw up to two parents above current tile, maybe prefetch parent
|
||||
*/
|
||||
public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
public class MapRenderer implements org.mapsforge.android.IMapRenderer {
|
||||
private static final String TAG = "MapRenderer";
|
||||
private static final int MB = 1024 * 1024;
|
||||
|
||||
private boolean mTriangulate = false;
|
||||
|
||||
private static int CACHE_TILES_MAX = 400;
|
||||
private static int CACHE_TILES = CACHE_TILES_MAX;
|
||||
private static final int LIMIT_BUFFERS = 32 * (1024 * 1024);
|
||||
private static int LIMIT_BUFFERS = 20 * MB;
|
||||
|
||||
private static final int OES_HALF_FLOAT = 0x8D61;
|
||||
private static final int FLOAT_BYTES = 4;
|
||||
@ -64,8 +117,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
private static int STENCIL_BITS = 8;
|
||||
|
||||
private final MapView mMapView;
|
||||
private final MapWorker mMapWorker;
|
||||
|
||||
private final ArrayList<MapGeneratorJob> mJobList;
|
||||
private final ArrayList<VertexBufferObject> mVBOs;
|
||||
private final TileCacheKey mTileCacheKey;
|
||||
@ -88,9 +139,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
// current center tile
|
||||
private long mTileX, mTileY;
|
||||
|
||||
private FloatBuffer floatBuffer = null;
|
||||
// private ByteBuffer byteBuffer = null;
|
||||
private ShortBuffer shortBuffer = null;
|
||||
private FloatBuffer floatBuffer[];
|
||||
private ShortBuffer shortBuffer[];
|
||||
|
||||
boolean useHalfFloat = false;
|
||||
|
||||
@ -147,7 +197,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
public MapRenderer(MapView mapView) {
|
||||
Log.d(TAG, "init MapRenderer");
|
||||
mMapView = mapView;
|
||||
mMapWorker = mapView.getMapWorker();
|
||||
mDebugSettings = mapView.getDebugSettings();
|
||||
|
||||
mVBOs = new ArrayList<VertexBufferObject>();
|
||||
@ -316,7 +365,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
mJobList.clear();
|
||||
mJobParameter = mMapView.getJobParameters();
|
||||
|
||||
IMapGenerator mapGenerator = mMapView.getMapGenerator();
|
||||
int tiles = 0;
|
||||
if (newTiles == null)
|
||||
return false;
|
||||
@ -376,19 +424,19 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
newTiles.tiles[tiles++] = tile;
|
||||
|
||||
if (!tile.isDrawn && !tile.newData && !tile.isLoading) {
|
||||
MapGeneratorJob job = new MapGeneratorJob(tile, mapGenerator,
|
||||
mJobParameter, mDebugSettings);
|
||||
MapGeneratorJob job = new MapGeneratorJob(tile, mJobParameter,
|
||||
mDebugSettings);
|
||||
mJobList.add(job);
|
||||
}
|
||||
|
||||
// prefetch parent
|
||||
if (tile.parent != null && !tile.parent.isDrawn && !tile.parent.newData
|
||||
&& !tile.parent.isLoading) {
|
||||
MapGeneratorJob job = new MapGeneratorJob(tile.parent, mapGenerator,
|
||||
mJobParameter, mDebugSettings);
|
||||
if (!mJobList.contains(job))
|
||||
mJobList.add(job);
|
||||
}
|
||||
// if (tile.parent != null && !tile.parent.isDrawn && !tile.parent.newData
|
||||
// && !tile.parent.isLoading) {
|
||||
// MapGeneratorJob job = new MapGeneratorJob(tile.parent, mJobParameter,
|
||||
// mDebugSettings);
|
||||
// if (!mJobList.contains(job))
|
||||
// mJobList.add(job);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,12 +467,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
|
||||
limitCache(removes);
|
||||
|
||||
if (mJobList.size() > 0) {
|
||||
mMapView.getJobQueue().setJobs(mJobList);
|
||||
synchronized (mMapWorker) {
|
||||
mMapWorker.notify();
|
||||
}
|
||||
}
|
||||
if (mJobList.size() > 0)
|
||||
mMapView.addJobs(mJobList);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -513,7 +557,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
|
||||
@Override
|
||||
public boolean passTile(MapGeneratorJob mapGeneratorJob) {
|
||||
if (!timing)
|
||||
if (!timing && mapGeneratorJob.tile.isVisible)
|
||||
mMapView.requestRender();
|
||||
return true;
|
||||
}
|
||||
@ -524,10 +568,10 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
boolean blend = false;
|
||||
|
||||
// draw to framebuffer
|
||||
GLES20.glColorMask(true, true, true, true);
|
||||
glColorMask(true, true, true, true);
|
||||
|
||||
// do not modify stencil buffer
|
||||
GLES20.glStencilMask(0);
|
||||
glStencilMask(0);
|
||||
|
||||
for (int c = 0; c < count; c++) {
|
||||
PolygonLayer l = mFillPolys[c];
|
||||
@ -541,26 +585,26 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
alpha = 1.0f;
|
||||
|
||||
if (!blend) {
|
||||
GLES20.glEnable(GLES20.GL_BLEND);
|
||||
glEnable(GL_BLEND);
|
||||
blend = true;
|
||||
}
|
||||
} else if (blend) {
|
||||
GLES20.glDisable(GLES20.GL_BLEND);
|
||||
glDisable(GL_BLEND);
|
||||
blend = false;
|
||||
}
|
||||
|
||||
GLES20.glUniform4f(gPolygonColorHandle,
|
||||
glUniform4f(gPolygonColorHandle,
|
||||
l.colors[0], l.colors[1], l.colors[2], alpha);
|
||||
|
||||
// set stencil buffer mask used to draw this layer
|
||||
GLES20.glStencilFunc(GLES20.GL_EQUAL, 0xff, 1 << c);
|
||||
glStencilFunc(GL_EQUAL, 0xff, 1 << c);
|
||||
|
||||
// draw tile fill coordinates
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
if (blend)
|
||||
GLES20.glDisable(GLES20.GL_BLEND);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
private boolean drawPolygons(GLMapTile tile, int diff) {
|
||||
@ -569,63 +613,68 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
if (tile.polygonLayers == null || tile.polygonLayers.array == null)
|
||||
return true;
|
||||
|
||||
GLES20.glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
|
||||
glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id);
|
||||
if (mLastBoundVBO != tile.polygonVBO.id) {
|
||||
mLastBoundVBO = tile.polygonVBO.id;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
|
||||
|
||||
if (useHalfFloat) {
|
||||
GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
|
||||
OES_HALF_FLOAT, false, 0,
|
||||
POLYGON_VERTICES_DATA_POS_OFFSET);
|
||||
} else {
|
||||
GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
|
||||
GLES20.GL_FLOAT, false, 0,
|
||||
POLYGON_VERTICES_DATA_POS_OFFSET);
|
||||
if (useHalfFloat) {
|
||||
glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
|
||||
OES_HALF_FLOAT, false, 0,
|
||||
POLYGON_VERTICES_DATA_POS_OFFSET);
|
||||
} else {
|
||||
glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
|
||||
GL_FLOAT, false, 0,
|
||||
POLYGON_VERTICES_DATA_POS_OFFSET);
|
||||
}
|
||||
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
setMatrix(tile, diff);
|
||||
GLES20.glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0);
|
||||
glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0);
|
||||
|
||||
boolean firstPass = true;
|
||||
|
||||
for (int i = 0, n = tile.polygonLayers.array.length; i < n; i++) {
|
||||
PolygonLayer l = tile.polygonLayers.array[i];
|
||||
|
||||
if (cnt == 0) {
|
||||
// disable drawing to framebuffer
|
||||
GLES20.glColorMask(false, false, false, false);
|
||||
|
||||
// never pass the test, i.e. always apply first stencil op (sfail)
|
||||
GLES20.glStencilFunc(GLES20.GL_NEVER, 0, 0xff);
|
||||
|
||||
if (firstPass)
|
||||
firstPass = false;
|
||||
else {
|
||||
// clear stencilbuffer
|
||||
GLES20.glStencilMask(0xFF);
|
||||
GLES20.glClear(GLES20.GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
// clear stencilbuffer (tile region)
|
||||
// GLES20.glStencilOp(GLES20.GL_ZERO, GLES20.GL_ZERO, GLES20.GL_ZERO);
|
||||
// GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
// stencil op for stencil method polygon drawing
|
||||
GLES20.glStencilOp(GLES20.GL_INVERT, GLES20.GL_INVERT, GLES20.GL_INVERT);
|
||||
}
|
||||
|
||||
// fade out polygon layers (set in RederTheme)
|
||||
if (l.fadeLevel > 0 && l.fadeLevel > mDrawZ)
|
||||
continue;
|
||||
|
||||
if (cnt == 0) {
|
||||
// disable drawing to framebuffer
|
||||
glColorMask(false, false, false, false);
|
||||
|
||||
// never pass the test, i.e. always apply first stencil op (sfail)
|
||||
glStencilFunc(GL_NEVER, 0, 0xff);
|
||||
|
||||
if (firstPass)
|
||||
firstPass = false;
|
||||
else {
|
||||
// eeek, nexus! - cant do old-school polygons
|
||||
// glFinish();
|
||||
|
||||
// clear stencilbuffer
|
||||
glStencilMask(0xFF);
|
||||
// glClear(GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
// clear stencilbuffer (tile region)
|
||||
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
// stencil op for stencil method polygon drawing
|
||||
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
|
||||
}
|
||||
|
||||
mFillPolys[cnt] = l;
|
||||
|
||||
// set stencil mask to draw to
|
||||
GLES20.glStencilMask(1 << cnt++);
|
||||
glStencilMask(1 << cnt++);
|
||||
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, l.offset, l.verticesCnt);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, l.offset, l.verticesCnt);
|
||||
|
||||
// draw up to 8 layers into stencil buffer
|
||||
if (cnt == STENCIL_BITS) {
|
||||
@ -634,47 +683,54 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
if (cnt > 0)
|
||||
if (cnt > 0) {
|
||||
fillPolygons(cnt);
|
||||
|
||||
// eeek, nexus! - cant do old-school polygons
|
||||
// glFinish();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private int mLastBoundVBO;
|
||||
|
||||
private boolean drawTriangles(GLMapTile tile, int diff) {
|
||||
|
||||
if (tile.meshLayers == null || tile.meshLayers.array == null)
|
||||
return true;
|
||||
|
||||
GLES20.glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
|
||||
glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id);
|
||||
if (mLastBoundVBO != tile.polygonVBO.id) {
|
||||
mLastBoundVBO = tile.polygonVBO.id;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
|
||||
|
||||
if (useHalfFloat) {
|
||||
GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
|
||||
OES_HALF_FLOAT, false, 0,
|
||||
POLYGON_VERTICES_DATA_POS_OFFSET);
|
||||
} else {
|
||||
GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
|
||||
GLES20.GL_FLOAT, false, 0,
|
||||
POLYGON_VERTICES_DATA_POS_OFFSET);
|
||||
if (useHalfFloat) {
|
||||
glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
|
||||
OES_HALF_FLOAT, false, 0,
|
||||
POLYGON_VERTICES_DATA_POS_OFFSET);
|
||||
} else {
|
||||
glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
|
||||
GL_FLOAT, false, 0,
|
||||
POLYGON_VERTICES_DATA_POS_OFFSET);
|
||||
}
|
||||
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
setMatrix(tile, diff);
|
||||
GLES20.glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0);
|
||||
glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0);
|
||||
|
||||
MeshLayer[] layers = tile.meshLayers.array;
|
||||
|
||||
for (int i = 0, n = layers.length; i < n; i++) {
|
||||
MeshLayer l = layers[i];
|
||||
GLES20.glUniform4fv(gPolygonColorHandle, 1, l.colors, 0);
|
||||
glUniform4fv(gPolygonColorHandle, 1, l.colors, 0);
|
||||
|
||||
// GLES20.glUniform4f(gPolygonColorHandle, 1, 0, 0, 1);
|
||||
// glUniform4f(gPolygonColorHandle, 1, 0, 0, 1);
|
||||
|
||||
// System.out.println("draw: " + l.offset + " " + l.verticesCnt);
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, l.offset, l.verticesCnt);
|
||||
glDrawArrays(GL_TRIANGLES, l.offset, l.verticesCnt);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -684,30 +740,32 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
if (tile.lineLayers == null || tile.lineLayers.array == null)
|
||||
return false;
|
||||
|
||||
GLES20.glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
|
||||
glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.id);
|
||||
if (mLastBoundVBO != tile.lineVBO.id) {
|
||||
mLastBoundVBO = tile.lineVBO.id;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id);
|
||||
|
||||
if (useHalfFloat) {
|
||||
GLES20.glVertexAttribPointer(gLineVertexPositionHandle, 2, OES_HALF_FLOAT,
|
||||
false, 8, LINE_VERTICES_DATA_POS_OFFSET);
|
||||
if (useHalfFloat) {
|
||||
glVertexAttribPointer(gLineVertexPositionHandle, 2, OES_HALF_FLOAT,
|
||||
false, 8, LINE_VERTICES_DATA_POS_OFFSET);
|
||||
|
||||
GLES20.glVertexAttribPointer(gLineTexturePositionHandle, 2, OES_HALF_FLOAT,
|
||||
false, 8, LINE_VERTICES_DATA_TEX_OFFSET >> 1);
|
||||
} else {
|
||||
GLES20.glVertexAttribPointer(gLineVertexPositionHandle, 2, GLES20.GL_FLOAT,
|
||||
false, 16, LINE_VERTICES_DATA_POS_OFFSET);
|
||||
glVertexAttribPointer(gLineTexturePositionHandle, 2, OES_HALF_FLOAT,
|
||||
false, 8, LINE_VERTICES_DATA_TEX_OFFSET >> 1);
|
||||
} else {
|
||||
glVertexAttribPointer(gLineVertexPositionHandle, 2, GL_FLOAT,
|
||||
false, 16, LINE_VERTICES_DATA_POS_OFFSET);
|
||||
|
||||
GLES20.glVertexAttribPointer(gLineTexturePositionHandle, 2, GLES20.GL_FLOAT,
|
||||
false, 16, LINE_VERTICES_DATA_TEX_OFFSET);
|
||||
glVertexAttribPointer(gLineTexturePositionHandle, 2, GL_FLOAT,
|
||||
false, 16, LINE_VERTICES_DATA_TEX_OFFSET);
|
||||
}
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
if (diff != 0)
|
||||
z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff);
|
||||
|
||||
setMatrix(tile, diff);
|
||||
GLES20.glUniformMatrix4fv(gLineMatrixHandle, 1, false, mMVPMatrix, 0);
|
||||
glUniformMatrix4fv(gLineMatrixHandle, 1, false, mMVPMatrix, 0);
|
||||
|
||||
LineLayer[] layers = tile.lineLayers.array;
|
||||
|
||||
@ -729,42 +787,37 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
drawFixed = l.isFixed;
|
||||
|
||||
if (drawOutlines) {
|
||||
GLES20.glUniform2f(gLineModeHandle, 0, wdiv);
|
||||
glUniform2f(gLineModeHandle, 0, wdiv);
|
||||
} else if (!drawFixed) {
|
||||
GLES20.glUniform2f(gLineModeHandle, 0, wdiv * 0.98f);
|
||||
glUniform2f(gLineModeHandle, 0, wdiv * 0.98f);
|
||||
}
|
||||
}
|
||||
|
||||
if (drawFixed) {
|
||||
if (l.width < 1.0)
|
||||
GLES20.glUniform2f(gLineModeHandle, 0.4f, fdiv);
|
||||
glUniform2f(gLineModeHandle, 0.4f, fdiv);
|
||||
else
|
||||
GLES20.glUniform2f(gLineModeHandle, 0, fdiv);
|
||||
glUniform2f(gLineModeHandle, 0, fdiv);
|
||||
}
|
||||
GLES20.glUniform4fv(gLineColorHandle, 1, l.colors, 0);
|
||||
glUniform4fv(gLineColorHandle, 1, l.colors, 0);
|
||||
|
||||
if (drawOutlines) {
|
||||
for (int j = 0, m = l.outlines.size(); j < m; j++) {
|
||||
LineLayer o = l.outlines.get(j);
|
||||
|
||||
if (mSimpleLines)
|
||||
GLES20.glUniform1f(gLineWidthHandle, o.width);
|
||||
glUniform1f(gLineWidthHandle, o.width);
|
||||
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (mSimpleLines)
|
||||
GLES20.glUniform1f(gLineWidthHandle, l.width);
|
||||
glUniform1f(gLineWidthHandle, l.width);
|
||||
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
|
||||
}
|
||||
// cnt += l.verticesCnt;
|
||||
}
|
||||
// GLES20.glUniform2f(gLineModeHandle, 0, wdiv);
|
||||
// float[] c = { 1, 0, 0, 1 };
|
||||
// GLES20.glUniform4fv(gLineColorHandle, 1, c, 0);
|
||||
// GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, cnt);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -940,47 +993,53 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean mTriangulate = false;
|
||||
|
||||
private int uploadCnt = 0;
|
||||
|
||||
private boolean uploadTileData(GLMapTile tile) {
|
||||
// not sure about this, but seems it fixes some flickering when
|
||||
// multiple tiles are uploaded in one go. but if this is really
|
||||
// the issue tiles should stay corrupted..
|
||||
|
||||
if (uploadCnt++ > 0)
|
||||
GLES20.glFinish();
|
||||
// double start = SystemClock.uptimeMillis();
|
||||
|
||||
// use multiple buffers to avoid overwriting buffer while current data is uploaded
|
||||
// (or rather the blocking which is required to avoid this)
|
||||
if (uploadCnt >= 10) {
|
||||
// mMapView.requestRender();
|
||||
// return false;
|
||||
uploadCnt = 0;
|
||||
glFinish();
|
||||
}
|
||||
|
||||
// Upload line data to vertex buffer object
|
||||
if (tile.lineVBO == null) {
|
||||
// Upload line data to vertex buffer object
|
||||
synchronized (mVBOs) {
|
||||
if (mVBOs.size() < 2)
|
||||
if (mVBOs.size() < 2) {
|
||||
Log.d(TAG, "uploadTileData, no VBOs left");
|
||||
return false;
|
||||
|
||||
}
|
||||
tile.lineVBO = mVBOs.remove(mVBOs.size() - 1);
|
||||
tile.polygonVBO = mVBOs.remove(mVBOs.size() - 1);
|
||||
}
|
||||
}
|
||||
if (useHalfFloat)
|
||||
shortBuffer = tile.lineLayers.compileLayerData(shortBuffer);
|
||||
shortBuffer[uploadCnt * 2] = tile.lineLayers
|
||||
.compileLayerData(shortBuffer[uploadCnt * 2]);
|
||||
else
|
||||
floatBuffer = tile.lineLayers.compileLayerData(floatBuffer);
|
||||
floatBuffer[uploadCnt * 2] = tile.lineLayers
|
||||
.compileLayerData(floatBuffer[uploadCnt * 2]);
|
||||
|
||||
if (tile.lineLayers.size > 0) {
|
||||
mBufferMemoryUsage -= tile.lineVBO.size;
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.id);
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null, GLES20.GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id);
|
||||
// glBufferData(GL_ARRAY_BUFFER, 0, null, GL_DYNAMIC_DRAW);
|
||||
|
||||
if (useHalfFloat) {
|
||||
tile.lineVBO.size = tile.lineLayers.size * SHORT_BYTES;
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.size,
|
||||
shortBuffer, GLES20.GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size,
|
||||
shortBuffer[uploadCnt * 2], GL_DYNAMIC_DRAW);
|
||||
} else {
|
||||
tile.lineVBO.size = tile.lineLayers.size * FLOAT_BYTES;
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.size,
|
||||
floatBuffer, GLES20.GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size,
|
||||
floatBuffer[uploadCnt * 2], GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
mBufferMemoryUsage += tile.lineVBO.size;
|
||||
@ -991,26 +1050,28 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
|
||||
if (!mTriangulate) {
|
||||
if (useHalfFloat)
|
||||
shortBuffer = tile.polygonLayers.compileLayerData(shortBuffer);
|
||||
shortBuffer[uploadCnt * 2 + 1] = tile.polygonLayers
|
||||
.compileLayerData(shortBuffer[uploadCnt * 2 + 1]);
|
||||
else
|
||||
floatBuffer = tile.polygonLayers.compileLayerData(floatBuffer);
|
||||
floatBuffer[uploadCnt * 2 + 1] = tile.polygonLayers
|
||||
.compileLayerData(floatBuffer[uploadCnt * 2 + 1]);
|
||||
|
||||
// Upload polygon data to vertex buffer object
|
||||
if (tile.polygonLayers.size > 0) {
|
||||
mBufferMemoryUsage -= tile.polygonVBO.size;
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id);
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null,
|
||||
GLES20.GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
|
||||
// glBufferData(GL_ARRAY_BUFFER, 0, null,
|
||||
// GL_DYNAMIC_DRAW);
|
||||
|
||||
if (useHalfFloat) {
|
||||
tile.polygonVBO.size = tile.polygonLayers.size * SHORT_BYTES;
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size,
|
||||
shortBuffer, GLES20.GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
|
||||
shortBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW);
|
||||
} else {
|
||||
tile.polygonVBO.size = tile.polygonLayers.size * FLOAT_BYTES;
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size,
|
||||
floatBuffer, GLES20.GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
|
||||
floatBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW);
|
||||
}
|
||||
mBufferMemoryUsage += tile.polygonVBO.size;
|
||||
|
||||
@ -1020,26 +1081,28 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
}
|
||||
else {
|
||||
if (useHalfFloat)
|
||||
shortBuffer = tile.meshLayers.compileLayerData(shortBuffer);
|
||||
shortBuffer[uploadCnt * 2 + 1] = tile.meshLayers
|
||||
.compileLayerData(shortBuffer[uploadCnt * 2 + 1]);
|
||||
else
|
||||
floatBuffer = tile.meshLayers.compileLayerData(floatBuffer);
|
||||
floatBuffer[uploadCnt * 2 + 1] = tile.meshLayers
|
||||
.compileLayerData(floatBuffer[uploadCnt * 2 + 1]);
|
||||
|
||||
// Upload triangle data to vertex buffer object
|
||||
if (tile.meshLayers.size > 0) {
|
||||
mBufferMemoryUsage -= tile.polygonVBO.size;
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id);
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null,
|
||||
GLES20.GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
|
||||
// glBufferData(GL_ARRAY_BUFFER, 0, null,
|
||||
// GL_DYNAMIC_DRAW);
|
||||
|
||||
if (useHalfFloat) {
|
||||
tile.polygonVBO.size = tile.meshLayers.size * SHORT_BYTES;
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size,
|
||||
shortBuffer, GLES20.GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
|
||||
shortBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW);
|
||||
} else {
|
||||
tile.polygonVBO.size = tile.meshLayers.size * FLOAT_BYTES;
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size,
|
||||
floatBuffer, GLES20.GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
|
||||
floatBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW);
|
||||
}
|
||||
mBufferMemoryUsage += tile.polygonVBO.size;
|
||||
|
||||
@ -1050,6 +1113,13 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
tile.newData = false;
|
||||
tile.isDrawn = true;
|
||||
tile.isLoading = false;
|
||||
// double compile = SystemClock.uptimeMillis();
|
||||
// glFinish();
|
||||
// double now = SystemClock.uptimeMillis();
|
||||
// Log.d(TAG, tile + " - upload took: " + (now - start) + " "
|
||||
// + (mBufferMemoryUsage / 1024) + "kb");
|
||||
|
||||
uploadCnt++;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1066,10 +1136,9 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
if (timing)
|
||||
start = SystemClock.uptimeMillis();
|
||||
|
||||
GLES20.glStencilMask(0xFF);
|
||||
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
|
||||
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT);
|
||||
// GLES20.glFlush();
|
||||
glStencilMask(0xFF);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
// long endTime = SystemClock.uptimeMillis();
|
||||
// long dt = endTime - startTime;
|
||||
@ -1100,22 +1169,21 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
GLMapTile[] tiles = curTiles.tiles;
|
||||
|
||||
if (mBufferMemoryUsage > LIMIT_BUFFERS) {
|
||||
Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / (1024 * 1024)
|
||||
+ "MB");
|
||||
Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / MB + "MB");
|
||||
synchronized (mVBOs) {
|
||||
for (VertexBufferObject vbo : mVBOs) {
|
||||
if (vbo.size == 0)
|
||||
continue;
|
||||
mBufferMemoryUsage -= vbo.size;
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id);
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null,
|
||||
GLES20.GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo.id);
|
||||
glBufferData(GL_ARRAY_BUFFER, 0, null,
|
||||
GL_DYNAMIC_DRAW);
|
||||
vbo.size = 0;
|
||||
|
||||
}
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
Log.d(TAG, " > " + mBufferMemoryUsage / (1024 * 1024) + "MB");
|
||||
Log.d(TAG, " > " + mBufferMemoryUsage / MB + "MB");
|
||||
|
||||
if (CACHE_TILES > 50)
|
||||
CACHE_TILES -= 50;
|
||||
@ -1124,6 +1192,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
}
|
||||
|
||||
uploadCnt = 0;
|
||||
mLastBoundVBO = -1;
|
||||
|
||||
// check visible tiles, set tile clip scissors, upload new vertex data
|
||||
for (int i = 0; i < tileCnt; i++) {
|
||||
@ -1134,11 +1203,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
|
||||
if (tile.newData) {
|
||||
uploadTileData(tile);
|
||||
|
||||
if (timing)
|
||||
Log.d(TAG, "buffer upload took: "
|
||||
+ (SystemClock.uptimeMillis() - start));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1158,23 +1222,25 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
}
|
||||
}
|
||||
}
|
||||
// GLES20.glFinish();
|
||||
GlUtils.checkGlError("upload");
|
||||
|
||||
if (GlUtils.checkGlOutOfMemory("upload: " + mBufferMemoryUsage)
|
||||
&& LIMIT_BUFFERS > MB)
|
||||
LIMIT_BUFFERS -= MB;
|
||||
|
||||
if (timing)
|
||||
clear_time = (SystemClock.uptimeMillis() - start);
|
||||
|
||||
GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
GLES20.glUseProgram(gPolygonProgram);
|
||||
// GLES20.glEnableVertexAttribArray(gPolygonVertexPositionHandle);
|
||||
glUseProgram(gPolygonProgram);
|
||||
glEnableVertexAttribArray(gPolygonVertexPositionHandle);
|
||||
|
||||
if (!mTriangulate) {
|
||||
GLES20.glDisable(GLES20.GL_BLEND);
|
||||
glDisable(GL_BLEND);
|
||||
// Draw Polygons
|
||||
GLES20.glEnable(GLES20.GL_STENCIL_TEST);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
||||
// GLES20.glEnableVertexAttribArray(gPolygonVertexPositionHandle);
|
||||
// glEnableVertexAttribArray(gPolygonVertexPositionHandle);
|
||||
|
||||
for (int i = 0; i < tileCnt; i++) {
|
||||
if (tiles[i].isVisible) {
|
||||
@ -1186,8 +1252,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
drawProxyPolygons(tile);
|
||||
}
|
||||
}
|
||||
GlUtils.checkGlError("polygons");
|
||||
GLES20.glDisable(GLES20.GL_STENCIL_TEST);
|
||||
// GlUtils.checkGlError("polygons");
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
} else {
|
||||
// Draw Triangles
|
||||
for (int i = 0; i < tileCnt; i++) {
|
||||
@ -1200,23 +1266,22 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
drawProxyTriangles(tile);
|
||||
}
|
||||
}
|
||||
GlUtils.checkGlError("triangles");
|
||||
// GlUtils.checkGlError("triangles");
|
||||
}
|
||||
// required on GalaxyII, Android 2.3.3
|
||||
// GLES20.glDisableVertexAttribArray(gPolygonVertexPositionHandle);
|
||||
// required on GalaxyII, Android 2.3.3 (cant just VAA enable once...)
|
||||
glDisableVertexAttribArray(gPolygonVertexPositionHandle);
|
||||
|
||||
if (timing) {
|
||||
GLES20.glFinish();
|
||||
glFinish();
|
||||
poly_time = (SystemClock.uptimeMillis() - start);
|
||||
}
|
||||
GLES20.glFlush();
|
||||
|
||||
// Draw lines
|
||||
GLES20.glEnable(GLES20.GL_BLEND);
|
||||
GLES20.glUseProgram(gLineProgram);
|
||||
glEnable(GL_BLEND);
|
||||
glUseProgram(gLineProgram);
|
||||
|
||||
// GLES20.glEnableVertexAttribArray(gLineVertexPositionHandle);
|
||||
// GLES20.glEnableVertexAttribArray(gLineTexturePositionHandle);
|
||||
glEnableVertexAttribArray(gLineVertexPositionHandle);
|
||||
glEnableVertexAttribArray(gLineTexturePositionHandle);
|
||||
|
||||
for (int i = 0; i < tileCnt; i++) {
|
||||
if (tiles[i].isVisible) {
|
||||
@ -1230,14 +1295,13 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
}
|
||||
|
||||
if (timing) {
|
||||
GLES20.glFinish();
|
||||
glFinish();
|
||||
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start) + " "
|
||||
+ clear_time + " " + poly_time);
|
||||
}
|
||||
// GLES20.glDisableVertexAttribArray(gLineVertexPositionHandle);
|
||||
// GLES20.glDisableVertexAttribArray(gLineTexturePositionHandle);
|
||||
GlUtils.checkGlError("lines");
|
||||
GLES20.glFinish();
|
||||
glDisableVertexAttribArray(gLineVertexPositionHandle);
|
||||
glDisableVertexAttribArray(gLineTexturePositionHandle);
|
||||
// GlUtils.checkGlError("lines");
|
||||
}
|
||||
|
||||
private int[] mVboIds;
|
||||
@ -1261,7 +1325,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
mHeight = height;
|
||||
mAspect = (float) height / width;
|
||||
|
||||
GLES20.glViewport(0, 0, width, height);
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
int tiles = (mWidth / Tile.TILE_SIZE + 4) * (mHeight / Tile.TILE_SIZE + 4);
|
||||
curTiles = new TilesData(tiles);
|
||||
@ -1271,7 +1335,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
// Set up vertex buffer objects
|
||||
int numVBO = (CACHE_TILES + tiles) * 2;
|
||||
mVboIds = new int[numVBO];
|
||||
GLES20.glGenBuffers(numVBO, mVboIds, 0);
|
||||
glGenBuffers(numVBO, mVboIds, 0);
|
||||
|
||||
for (int i = 0; i < numVBO; i++)
|
||||
mVBOs.add(new VertexBufferObject(mVboIds[i]));
|
||||
@ -1302,21 +1366,25 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
||||
String ext = glGetString(GL_EXTENSIONS);
|
||||
|
||||
if (ext.indexOf("GL_OES_vertex_half_float") >= 0)
|
||||
if (ext.indexOf("GL_OES_vertex_half_float") >= 0) {
|
||||
useHalfFloat = true;
|
||||
|
||||
shortBuffer = new ShortBuffer[20];
|
||||
}
|
||||
else {
|
||||
floatBuffer = new FloatBuffer[20];
|
||||
}
|
||||
Log.d(TAG, "Extensions: " + ext);
|
||||
|
||||
gLineMatrixHandle = GLES20.glGetUniformLocation(gLineProgram, "u_center");
|
||||
gLineModeHandle = GLES20.glGetUniformLocation(gLineProgram, "u_mode");
|
||||
gLineColorHandle = GLES20.glGetUniformLocation(gLineProgram, "u_color");
|
||||
gLineMatrixHandle = glGetUniformLocation(gLineProgram, "u_center");
|
||||
gLineModeHandle = glGetUniformLocation(gLineProgram, "u_mode");
|
||||
gLineColorHandle = glGetUniformLocation(gLineProgram, "u_color");
|
||||
gLineVertexPositionHandle = GLES20
|
||||
.glGetAttribLocation(gLineProgram, "a_position");
|
||||
gLineTexturePositionHandle = GLES20.glGetAttribLocation(gLineProgram, "a_st");
|
||||
gLineTexturePositionHandle = glGetAttribLocation(gLineProgram, "a_st");
|
||||
if (mSimpleLines)
|
||||
gLineWidthHandle = GLES20.glGetUniformLocation(gLineProgram, "u_width");
|
||||
gLineWidthHandle = glGetUniformLocation(gLineProgram, "u_width");
|
||||
|
||||
// Set up the program for rendering polygons
|
||||
gPolygonProgram = GlUtils.createProgram(Shaders.gPolygonVertexShader,
|
||||
@ -1325,31 +1393,39 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
Log.e(TAG, "Could not create polygon program.");
|
||||
return;
|
||||
}
|
||||
gPolygonMatrixHandle = GLES20.glGetUniformLocation(gPolygonProgram, "u_center");
|
||||
gPolygonVertexPositionHandle = GLES20.glGetAttribLocation(gPolygonProgram,
|
||||
gPolygonMatrixHandle = glGetUniformLocation(gPolygonProgram, "u_center");
|
||||
gPolygonVertexPositionHandle = glGetAttribLocation(gPolygonProgram,
|
||||
"a_position");
|
||||
gPolygonColorHandle = GLES20.glGetUniformLocation(gPolygonProgram, "u_color");
|
||||
gPolygonColorHandle = glGetUniformLocation(gPolygonProgram, "u_color");
|
||||
|
||||
GLES20.glUseProgram(gPolygonProgram);
|
||||
GLES20.glEnableVertexAttribArray(gPolygonVertexPositionHandle);
|
||||
// glUseProgram(gPolygonProgram);
|
||||
// glEnableVertexAttribArray(gPolygonVertexPositionHandle);
|
||||
//
|
||||
// glUseProgram(gLineProgram);
|
||||
// glEnableVertexAttribArray(gLineVertexPositionHandle);
|
||||
// glEnableVertexAttribArray(gLineTexturePositionHandle);
|
||||
|
||||
GLES20.glUseProgram(gLineProgram);
|
||||
GLES20.glEnableVertexAttribArray(gLineVertexPositionHandle);
|
||||
GLES20.glEnableVertexAttribArray(gLineTexturePositionHandle);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
|
||||
GLES20.glDepthMask(false);
|
||||
GLES20.glDisable(GLES20.GL_DITHER);
|
||||
GLES20.glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
|
||||
GLES20.glClearStencil(0);
|
||||
|
||||
// GLES20.glFrontFace(GLES20.GL_CCW);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(false);
|
||||
glDisable(GL_DITHER);
|
||||
glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
|
||||
glClearStencil(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processedTile() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public IMapGenerator getMapGenerator() {
|
||||
return new MapGenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMapGenerator createMapGenerator() {
|
||||
return new MapGenerator();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ class PolygonLayers {
|
||||
// Log.d("GLMap", "allocate buffer " + size);
|
||||
fbuf = bbuf.asFloatBuffer();
|
||||
} else {
|
||||
fbuf.position(0);
|
||||
fbuf.clear();
|
||||
}
|
||||
|
||||
fbuf.put(mFillCoords, 0, 8);
|
||||
@ -95,7 +95,7 @@ class PolygonLayers {
|
||||
l.pool = null;
|
||||
}
|
||||
|
||||
fbuf.position(0);
|
||||
fbuf.flip();
|
||||
|
||||
// not needed for drawing
|
||||
layers = null;
|
||||
@ -121,7 +121,7 @@ class PolygonLayers {
|
||||
ByteOrder.nativeOrder());
|
||||
sbuf = bbuf.asShortBuffer();
|
||||
} else {
|
||||
sbuf.position(0);
|
||||
sbuf.clear();
|
||||
}
|
||||
|
||||
short[] data = new short[PoolItem.SIZE];
|
||||
@ -157,7 +157,7 @@ class PolygonLayers {
|
||||
l.pool = null;
|
||||
}
|
||||
|
||||
sbuf.position(0);
|
||||
sbuf.flip();
|
||||
|
||||
// not needed for drawing
|
||||
layers = null;
|
||||
|
||||
@ -14,9 +14,7 @@
|
||||
*/
|
||||
package org.mapsforge.android.mapgenerator;
|
||||
|
||||
import org.mapsforge.android.MapRenderer;
|
||||
import org.mapsforge.android.MapView;
|
||||
import org.mapsforge.core.GeoPoint;
|
||||
import org.mapsforge.android.rendertheme.RenderTheme;
|
||||
import org.mapsforge.database.IMapDatabase;
|
||||
|
||||
/**
|
||||
@ -37,31 +35,13 @@ public interface IMapGenerator {
|
||||
*/
|
||||
boolean executeJob(MapGeneratorJob mapGeneratorJob);
|
||||
|
||||
/**
|
||||
* @return the start point of this MapGenerator (may be null).
|
||||
*/
|
||||
GeoPoint getStartPoint();
|
||||
|
||||
/**
|
||||
* @return the start zoom level of this MapGenerator (may be null).
|
||||
*/
|
||||
Byte getStartZoomLevel();
|
||||
|
||||
/**
|
||||
* @return the maximum zoom level that this MapGenerator supports.
|
||||
*/
|
||||
byte getZoomLevelMax();
|
||||
|
||||
/**
|
||||
* @param mapView
|
||||
* the MapView
|
||||
* @return GLSurfaceView Renderer
|
||||
*/
|
||||
MapRenderer getMapRenderer(MapView mapView);
|
||||
|
||||
/**
|
||||
* @param mapDatabase
|
||||
* the MapDatabase from which the map data will be read.
|
||||
*/
|
||||
void setMapDatabase(IMapDatabase mapDatabase);
|
||||
|
||||
IMapDatabase getMapDatabase();
|
||||
|
||||
void setRenderTheme(RenderTheme theme);
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ public class JobParameters {
|
||||
/**
|
||||
* The render theme which should be used.
|
||||
*/
|
||||
public final JobTheme jobTheme;
|
||||
public final Theme theme;
|
||||
|
||||
/**
|
||||
* The text scale factor which should applied to the render theme.
|
||||
@ -32,13 +32,13 @@ public class JobParameters {
|
||||
private final int mHashCodeValue;
|
||||
|
||||
/**
|
||||
* @param jobTheme
|
||||
* @param theme
|
||||
* render theme which should be used.
|
||||
* @param textScale
|
||||
* the text scale factor which should applied to the render theme.
|
||||
*/
|
||||
public JobParameters(JobTheme jobTheme, float textScale) {
|
||||
this.jobTheme = jobTheme;
|
||||
public JobParameters(Theme theme, float textScale) {
|
||||
this.theme = theme;
|
||||
this.textScale = textScale;
|
||||
mHashCodeValue = calculateHashCode();
|
||||
}
|
||||
@ -52,11 +52,11 @@ public class JobParameters {
|
||||
return false;
|
||||
}
|
||||
JobParameters other = (JobParameters) obj;
|
||||
if (jobTheme == null) {
|
||||
if (other.jobTheme != null) {
|
||||
if (theme == null) {
|
||||
if (other.theme != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!jobTheme.equals(other.jobTheme)) {
|
||||
} else if (!theme.equals(other.theme)) {
|
||||
return false;
|
||||
}
|
||||
if (Float.floatToIntBits(textScale) != Float.floatToIntBits(other.textScale)) {
|
||||
@ -75,7 +75,7 @@ public class JobParameters {
|
||||
*/
|
||||
private int calculateHashCode() {
|
||||
int result = 7;
|
||||
result = 31 * result + ((jobTheme == null) ? 0 : jobTheme.hashCode());
|
||||
result = 31 * result + ((theme == null) ? 0 : theme.hashCode());
|
||||
result = 31 * result + Float.floatToIntBits(textScale);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -103,7 +103,8 @@ public class JobQueue {
|
||||
* Schedules all jobs in this queue.
|
||||
*/
|
||||
private void schedule() {
|
||||
PriorityQueue<MapGeneratorJob> tempJobQueue = new PriorityQueue<MapGeneratorJob>(INITIAL_CAPACITY);
|
||||
PriorityQueue<MapGeneratorJob> tempJobQueue = new PriorityQueue<MapGeneratorJob>(
|
||||
INITIAL_CAPACITY);
|
||||
|
||||
TileScheduler.time = SystemClock.uptimeMillis();
|
||||
TileScheduler.mapPosition = mMapView.getMapPosition().getMapPosition();
|
||||
|
||||
@ -37,29 +37,40 @@ public final class MapDatabaseFactory {
|
||||
return new org.mapsforge.database.postgis.MapDatabase();
|
||||
}
|
||||
|
||||
MapDatabaseInternal mapDatabaseInternal = MapDatabaseInternal
|
||||
.valueOf(mapDatabaseName);
|
||||
MapDatabases mapDatabaseInternal = MapDatabases.valueOf(mapDatabaseName);
|
||||
|
||||
return MapDatabaseFactory.createMapDatabase(mapDatabaseInternal);
|
||||
}
|
||||
|
||||
public static MapDatabases getMapDatabase(AttributeSet attributeSet) {
|
||||
String mapDatabaseName = attributeSet.getAttributeValue(null,
|
||||
MAP_DATABASE_ATTRIBUTE_NAME);
|
||||
if (mapDatabaseName == null) {
|
||||
return MapDatabases.POSTGIS_READER;
|
||||
}
|
||||
|
||||
return MapDatabases.valueOf(mapDatabaseName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mapDatabaseInternal
|
||||
* @param mapDatabase
|
||||
* the internal MapDatabase implementation.
|
||||
* @return a new MapGenerator instance.
|
||||
*/
|
||||
public static IMapDatabase createMapDatabase(MapDatabaseInternal mapDatabaseInternal) {
|
||||
switch (mapDatabaseInternal) {
|
||||
public static IMapDatabase createMapDatabase(MapDatabases mapDatabase) {
|
||||
switch (mapDatabase) {
|
||||
case MAP_READER:
|
||||
return new org.mapsforge.database.mapfile.MapDatabase();
|
||||
case JSON_READER:
|
||||
return new org.mapsforge.database.json.MapDatabase();
|
||||
case POSTGIS_READER:
|
||||
return new org.mapsforge.database.postgis.MapDatabase();
|
||||
case PBMAP_READER:
|
||||
return new org.mapsforge.database.pbmap.MapDatabase();
|
||||
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("unknown enum value: " + mapDatabaseInternal);
|
||||
throw new IllegalArgumentException("unknown enum value: " + mapDatabase);
|
||||
}
|
||||
|
||||
private MapDatabaseFactory() {
|
||||
|
||||
@ -17,7 +17,7 @@ package org.mapsforge.android.mapgenerator;
|
||||
/**
|
||||
* MapDatabase Implementations
|
||||
*/
|
||||
public enum MapDatabaseInternal {
|
||||
public enum MapDatabases {
|
||||
/**
|
||||
* ...
|
||||
*/
|
||||
@ -33,4 +33,8 @@ public enum MapDatabaseInternal {
|
||||
*/
|
||||
POSTGIS_READER,
|
||||
|
||||
/**
|
||||
* ...
|
||||
*/
|
||||
PBMAP_READER,
|
||||
}
|
||||
@ -37,7 +37,7 @@ public class MapGeneratorJob implements Comparable<MapGeneratorJob>, Serializabl
|
||||
/**
|
||||
* The rendering parameters for this job.
|
||||
*/
|
||||
public final JobParameters jobParameters;
|
||||
// public final JobParameters jobParameters;
|
||||
|
||||
/**
|
||||
* The tile which should be generated.
|
||||
@ -45,7 +45,6 @@ public class MapGeneratorJob implements Comparable<MapGeneratorJob>, Serializabl
|
||||
public final MapTile tile;
|
||||
|
||||
private transient int mHashCodeValue;
|
||||
private final IMapGenerator mMapGenerator;
|
||||
private transient double mPriority;
|
||||
|
||||
/**
|
||||
@ -90,18 +89,15 @@ public class MapGeneratorJob implements Comparable<MapGeneratorJob>, Serializabl
|
||||
*
|
||||
* @param _tile
|
||||
* the tile which should be generated.
|
||||
* @param mapGenerator
|
||||
* the MapGenerator for this job.
|
||||
* @param _jobParameters
|
||||
* the rendering parameters for this job.
|
||||
* @param _debugSettings
|
||||
* the debug settings for this job.
|
||||
*/
|
||||
public MapGeneratorJob(MapTile _tile, IMapGenerator mapGenerator,
|
||||
JobParameters _jobParameters, DebugSettings _debugSettings) {
|
||||
public MapGeneratorJob(MapTile _tile, JobParameters _jobParameters,
|
||||
DebugSettings _debugSettings) {
|
||||
tile = _tile;
|
||||
mMapGenerator = mapGenerator;
|
||||
jobParameters = _jobParameters;
|
||||
// jobParameters = _jobParameters;
|
||||
debugSettings = _debugSettings;
|
||||
calculateTransientValues();
|
||||
}
|
||||
@ -133,16 +129,14 @@ public class MapGeneratorJob implements Comparable<MapGeneratorJob>, Serializabl
|
||||
} 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 (mMapGenerator != other.mMapGenerator) {
|
||||
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;
|
||||
@ -164,8 +158,7 @@ public class MapGeneratorJob implements Comparable<MapGeneratorJob>, Serializabl
|
||||
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 + ((mMapGenerator == null) ? 0 : mMapGenerator.hashCode());
|
||||
// result = 31 * result + ((jobParameters == null) ? 0 : jobParameters.hashCode());
|
||||
result = 31 * result + ((tile == null) ? 0 : tile.hashCode());
|
||||
return result;
|
||||
}
|
||||
@ -177,7 +170,8 @@ public class MapGeneratorJob implements Comparable<MapGeneratorJob>, Serializabl
|
||||
mHashCodeValue = calculateHashCode();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
|
||||
private void readObject(ObjectInputStream objectInputStream) throws IOException,
|
||||
ClassNotFoundException {
|
||||
objectInputStream.defaultReadObject();
|
||||
calculateTransientValues();
|
||||
}
|
||||
|
||||
@ -14,46 +14,66 @@
|
||||
*/
|
||||
package org.mapsforge.android.mapgenerator;
|
||||
|
||||
import org.mapsforge.android.IMapRenderer;
|
||||
import org.mapsforge.android.MapView;
|
||||
|
||||
import android.util.AttributeSet;
|
||||
|
||||
/**
|
||||
* A factory for the internal MapGenerator implementations.
|
||||
*/
|
||||
public final class MapGeneratorFactory {
|
||||
public final class MapRendererFactory {
|
||||
private static final String MAP_GENERATOR_ATTRIBUTE_NAME = "mapGenerator";
|
||||
|
||||
/**
|
||||
* @param mapView
|
||||
* ...
|
||||
* @param attributeSet
|
||||
* A collection of attributes which includes the desired MapGenerator.
|
||||
* @return a new MapGenerator instance.
|
||||
*/
|
||||
public static IMapGenerator createMapGenerator(AttributeSet attributeSet) {
|
||||
String mapGeneratorName = attributeSet.getAttributeValue(null, MAP_GENERATOR_ATTRIBUTE_NAME);
|
||||
public static IMapRenderer createMapRenderer(MapView mapView,
|
||||
AttributeSet attributeSet) {
|
||||
String mapGeneratorName = attributeSet.getAttributeValue(null,
|
||||
MAP_GENERATOR_ATTRIBUTE_NAME);
|
||||
if (mapGeneratorName == null) {
|
||||
return new org.mapsforge.android.glrenderer.DatabaseRenderer();
|
||||
return new org.mapsforge.android.glrenderer.MapRenderer(mapView);
|
||||
}
|
||||
|
||||
MapGeneratorInternal mapGeneratorInternal = MapGeneratorInternal.valueOf(mapGeneratorName);
|
||||
return MapGeneratorFactory.createMapGenerator(mapGeneratorInternal);
|
||||
MapRenderers mapGeneratorInternal = MapRenderers.valueOf(mapGeneratorName);
|
||||
return MapRendererFactory.createMapRenderer(mapView, mapGeneratorInternal);
|
||||
}
|
||||
|
||||
public static MapRenderers getMapGenerator(AttributeSet attributeSet) {
|
||||
String mapGeneratorName = attributeSet.getAttributeValue(null,
|
||||
MAP_GENERATOR_ATTRIBUTE_NAME);
|
||||
if (mapGeneratorName == null) {
|
||||
return MapRenderers.GL_RENDERER;
|
||||
}
|
||||
|
||||
return MapRenderers.valueOf(mapGeneratorName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mapView
|
||||
* ...
|
||||
* @param mapGeneratorInternal
|
||||
* the internal MapGenerator implementation.
|
||||
* @return a new MapGenerator instance.
|
||||
*/
|
||||
public static IMapGenerator createMapGenerator(MapGeneratorInternal mapGeneratorInternal) {
|
||||
public static IMapRenderer createMapRenderer(MapView mapView,
|
||||
MapRenderers mapGeneratorInternal) {
|
||||
switch (mapGeneratorInternal) {
|
||||
case SW_RENDERER:
|
||||
return new org.mapsforge.android.swrenderer.DatabaseRenderer();
|
||||
return new org.mapsforge.android.swrenderer.MapRenderer(mapView);
|
||||
case GL_RENDERER:
|
||||
return new org.mapsforge.android.glrenderer.DatabaseRenderer();
|
||||
return new org.mapsforge.android.glrenderer.MapRenderer(mapView);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("unknown enum value: " + mapGeneratorInternal);
|
||||
}
|
||||
|
||||
private MapGeneratorFactory() {
|
||||
private MapRendererFactory() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
@ -17,7 +17,7 @@ package org.mapsforge.android.mapgenerator;
|
||||
/**
|
||||
* Enumeration of all internal MapGenerator implementations.
|
||||
*/
|
||||
public enum MapGeneratorInternal {
|
||||
public enum MapRenderers {
|
||||
/**
|
||||
* texture renderer.
|
||||
*/
|
||||
@ -14,7 +14,7 @@
|
||||
*/
|
||||
package org.mapsforge.android.mapgenerator;
|
||||
|
||||
import org.mapsforge.android.MapRenderer;
|
||||
import org.mapsforge.android.IMapRenderer;
|
||||
import org.mapsforge.android.MapView;
|
||||
import org.mapsforge.android.utils.PausableThread;
|
||||
|
||||
@ -23,35 +23,33 @@ import org.mapsforge.android.utils.PausableThread;
|
||||
* thread.
|
||||
*/
|
||||
public class MapWorker extends PausableThread {
|
||||
private static final String THREAD_NAME = "MapWorker";
|
||||
|
||||
private final String THREAD_NAME;
|
||||
private final JobQueue mJobQueue;
|
||||
private IMapGenerator mMapGenerator;
|
||||
private MapRenderer mMapRenderer;
|
||||
private final IMapGenerator mMapGenerator;
|
||||
private final IMapRenderer mMapRenderer;
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* thread id
|
||||
* @param mapView
|
||||
* the MapView for which this MapWorker generates map tiles.
|
||||
* @param mapGenerator
|
||||
* ...
|
||||
* @param mapRenderer
|
||||
* ...
|
||||
*/
|
||||
public MapWorker(MapView mapView) {
|
||||
public MapWorker(int id, MapView mapView, IMapGenerator mapGenerator,
|
||||
IMapRenderer mapRenderer) {
|
||||
super();
|
||||
mJobQueue = mapView.getJobQueue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mapGenerator
|
||||
* the MapGenerator which this MapWorker should use.
|
||||
*/
|
||||
public void setMapGenerator(IMapGenerator mapGenerator) {
|
||||
mMapGenerator = mapGenerator;
|
||||
mMapRenderer = mapRenderer;
|
||||
|
||||
THREAD_NAME = "MapWorker" + id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mapRenderer
|
||||
* the MapRenderer
|
||||
*/
|
||||
public void setMapRenderer(MapRenderer mapRenderer) {
|
||||
mMapRenderer = mapRenderer;
|
||||
public IMapGenerator getMapGenerator() {
|
||||
return mMapGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -65,6 +63,7 @@ public class MapWorker extends PausableThread {
|
||||
|
||||
if (mMapGenerator == null || mapGeneratorJob == null)
|
||||
return;
|
||||
// Log.d(THREAD_NAME, "processing: " + mapGeneratorJob.tile);
|
||||
|
||||
boolean success = mMapGenerator.executeJob(mapGeneratorJob);
|
||||
|
||||
@ -80,7 +79,8 @@ public class MapWorker extends PausableThread {
|
||||
|
||||
@Override
|
||||
protected int getThreadPriority() {
|
||||
return (Thread.NORM_PRIORITY + Thread.MIN_PRIORITY) / 2;
|
||||
// return (Thread.NORM_PRIORITY + Thread.MIN_PRIORITY) / 2;
|
||||
return Thread.MIN_PRIORITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -21,7 +21,7 @@ import java.io.Serializable;
|
||||
/**
|
||||
* A JobTheme defines the render theme which is used for a {@link MapGeneratorJob}.
|
||||
*/
|
||||
public interface JobTheme extends Serializable {
|
||||
public interface Theme extends Serializable {
|
||||
/**
|
||||
* @return an InputStream to read the render theme data from.
|
||||
* @throws FileNotFoundException
|
||||
@ -21,12 +21,12 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
|
||||
import org.mapsforge.android.mapgenerator.JobTheme;
|
||||
import org.mapsforge.android.mapgenerator.Theme;
|
||||
|
||||
/**
|
||||
* An ExternalRenderTheme allows for customizing the rendering style of the map via an XML file.
|
||||
*/
|
||||
public class ExternalRenderTheme implements JobTheme {
|
||||
public class ExternalRenderTheme implements Theme {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final long mFileModificationDate;
|
||||
|
||||
@ -16,12 +16,12 @@ package org.mapsforge.android.rendertheme;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.mapsforge.android.mapgenerator.JobTheme;
|
||||
import org.mapsforge.android.mapgenerator.Theme;
|
||||
|
||||
/**
|
||||
* Enumeration of all internal rendering themes.
|
||||
*/
|
||||
public enum InternalRenderTheme implements JobTheme {
|
||||
public enum InternalRenderTheme implements Theme {
|
||||
/**
|
||||
* A rendering theme similar to the OpenStreetMap Osmarender style.
|
||||
*
|
||||
@ -37,6 +37,9 @@ public enum InternalRenderTheme implements JobTheme {
|
||||
|
||||
@Override
|
||||
public InputStream getRenderThemeAsStream() {
|
||||
return Thread.currentThread().getClass().getResourceAsStream(mPath);
|
||||
// getResourceAsStream(mPath);
|
||||
return InternalRenderTheme.class.getResourceAsStream(mPath);
|
||||
// return Thread.currentThread().getClass().getResourceAsStream(mPath);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,10 +87,6 @@ public class RenderTheme {
|
||||
private final LRUCache<MatchingCacheKey, RenderInstruction[]> mMatchingCacheWay;
|
||||
private final LRUCache<MatchingCacheKey, RenderInstruction[]> mMatchingCacheArea;
|
||||
|
||||
// private List<RenderInstruction> mMatchingListWay;
|
||||
// private List<RenderInstruction> mMatchingListArea;
|
||||
// private List<RenderInstruction> mMatchingListNode;
|
||||
|
||||
RenderTheme(int mapBackground, float baseStrokeWidth, float baseTextSize) {
|
||||
mMapBackground = mapBackground;
|
||||
mBaseStrokeWidth = baseStrokeWidth;
|
||||
@ -198,7 +194,7 @@ public class RenderTheme {
|
||||
}
|
||||
}
|
||||
|
||||
private RenderInstruction[] mRenderInstructions = null;
|
||||
// private RenderInstruction[] mRenderInstructions = null;
|
||||
|
||||
/**
|
||||
* Matches a way with the given parameters against this RenderTheme.
|
||||
@ -213,23 +209,26 @@ public class RenderTheme {
|
||||
* way is Closed
|
||||
* @param changed
|
||||
* ...
|
||||
* @return currently processed render instructions
|
||||
*/
|
||||
public void matchWay(IRenderCallback renderCallback, Tag[] tags, byte zoomLevel,
|
||||
public synchronized RenderInstruction[] matchWay(IRenderCallback renderCallback,
|
||||
Tag[] tags,
|
||||
byte zoomLevel,
|
||||
boolean closed, boolean changed) {
|
||||
RenderInstruction[] renderInstructions = null;
|
||||
|
||||
LRUCache<MatchingCacheKey, RenderInstruction[]> matchingCache;
|
||||
MatchingCacheKey matchingCacheKey;
|
||||
|
||||
if (!changed) {
|
||||
renderInstructions = mRenderInstructions;
|
||||
|
||||
if (renderInstructions != null) {
|
||||
for (int i = 0, n = renderInstructions.length; i < n; i++)
|
||||
renderInstructions[i].renderWay(renderCallback, tags);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// if (!changed) {
|
||||
// renderInstructions = mRenderInstructions;
|
||||
//
|
||||
// if (renderInstructions != null) {
|
||||
// for (int i = 0, n = renderInstructions.length; i < n; i++)
|
||||
// renderInstructions[i].renderWay(renderCallback, tags);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (closed) {
|
||||
matchingCache = mMatchingCacheArea;
|
||||
@ -267,90 +266,8 @@ public class RenderTheme {
|
||||
matchingCache.put(matchingCacheKey, renderInstructions);
|
||||
}
|
||||
|
||||
mRenderInstructions = renderInstructions;
|
||||
|
||||
// if (matchingList != null) {
|
||||
// for (int i = 0, n = matchingList.size(); i < n; ++i) {
|
||||
// matchingList.get(i).renderWay(renderCallback, tags);
|
||||
// }
|
||||
// }
|
||||
// return renderInstructions;
|
||||
|
||||
// if (closed) {
|
||||
// mMatchingListArea = matchingList;
|
||||
// } else {
|
||||
// mMatchingListWay = matchingList;
|
||||
// }
|
||||
|
||||
// if (mCompareKey.set(tags, zoomLevel, closed)) {
|
||||
// // Log.d("mapsforge", "SAME AS BAFORE!!!" + tags);
|
||||
// for (int i = 0, n = mInstructionList.length; i < n; ++i) {
|
||||
// mInstructionList[i].renderWay(renderCallback, tags);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// SparseArray<RenderInstruction[]> matchingList = mMatchingCache.get(mCompareKey);
|
||||
//
|
||||
// if (matchingList != null) {
|
||||
// mInstructionList = matchingList.get(zoomLevel);
|
||||
// if (mInstructionList != null) {
|
||||
// // cache hit
|
||||
// // Log.d("mapsforge", "CCACHE HIT !!!" + tags);
|
||||
// for (int i = 0, n = mInstructionList.length; i < n; ++i) {
|
||||
// mInstructionList[i].renderWay(renderCallback, tags);
|
||||
// }
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// // Log.d("mapsforge", "CACHE MISS !!!" + tags);
|
||||
// // cache miss
|
||||
// ArrayList<RenderInstruction> instructionList = new ArrayList<RenderInstruction>();
|
||||
//
|
||||
// for (int i = 0, n = mRulesList.size(); i < n; ++i) {
|
||||
// mRulesList.get(i).matchWay(renderCallback, mCompareKey.getTags(), zoomLevel, closed, instructionList);
|
||||
// }
|
||||
//
|
||||
// boolean found = false;
|
||||
// int size = instructionList.size();
|
||||
//
|
||||
// if (matchingList == null) {
|
||||
// matchingList = new SparseArray<RenderInstruction[]>(25);
|
||||
// MatchingCacheKey matchingCacheKey = new MatchingCacheKey(mCompareKey);
|
||||
// mMatchingCache.put(matchingCacheKey, matchingList);
|
||||
// } else {
|
||||
// // check if another zoomLevel uses the same instructionList
|
||||
// for (int i = 0, n = matchingList.size(); i < n; i++) {
|
||||
// int key = matchingList.keyAt(i);
|
||||
//
|
||||
// RenderInstruction[] list2 = matchingList.get(key);
|
||||
// if (list2.length != size)
|
||||
// continue;
|
||||
//
|
||||
// int j = 0;
|
||||
// while (j < size && (list2[j] == instructionList.get(j)))
|
||||
// j++;
|
||||
//
|
||||
// if (j == size) {
|
||||
// instructionList.clear();
|
||||
// mInstructionList = list2;
|
||||
// found = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!found) {
|
||||
// mInstructionList = new RenderInstruction[size];
|
||||
// for (int i = 0; i < size; i++)
|
||||
// mInstructionList[i] = instructionList.get(i);
|
||||
// }
|
||||
//
|
||||
// for (int i = 0, n = mInstructionList.length; i < n; ++i)
|
||||
// mInstructionList[i].renderWay(renderCallback, tags);
|
||||
//
|
||||
// matchingList.put(zoomLevel, mInstructionList);
|
||||
// mRenderInstructions = renderInstructions;
|
||||
return renderInstructions;
|
||||
}
|
||||
|
||||
void addRule(Rule rule) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -14,77 +14,39 @@
|
||||
*/
|
||||
package org.mapsforge.android.swrenderer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.mapsforge.android.MapView;
|
||||
import org.mapsforge.android.mapgenerator.IMapGenerator;
|
||||
import org.mapsforge.android.mapgenerator.JobTheme;
|
||||
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
|
||||
import org.mapsforge.android.mapgenerator.Theme;
|
||||
import org.mapsforge.android.rendertheme.IRenderCallback;
|
||||
import org.mapsforge.android.rendertheme.RenderTheme;
|
||||
import org.mapsforge.android.rendertheme.RenderThemeHandler;
|
||||
import org.mapsforge.android.rendertheme.renderinstruction.Area;
|
||||
import org.mapsforge.android.rendertheme.renderinstruction.Line;
|
||||
import org.mapsforge.core.GeoPoint;
|
||||
import org.mapsforge.core.Tag;
|
||||
import org.mapsforge.core.Tile;
|
||||
import org.mapsforge.database.IMapDatabase;
|
||||
import org.mapsforge.database.IMapDatabaseCallback;
|
||||
import org.mapsforge.database.MapFileInfo;
|
||||
import org.mapsforge.database.mapfile.MapDatabase;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.util.FloatMath;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A DatabaseRenderer renders map tiles by reading from a {@link MapDatabase}.
|
||||
*/
|
||||
public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
public class MapGenerator implements IMapGenerator, IRenderCallback,
|
||||
IMapDatabaseCallback {
|
||||
private static String TAG = DatabaseRenderer.class.getName();
|
||||
private static final Byte DEFAULT_START_ZOOM_LEVEL = Byte.valueOf((byte) 12);
|
||||
// private static String TAG = MapGenerator.class.getName();
|
||||
private static final byte LAYERS = 11;
|
||||
private static final Paint PAINT_WATER_TILE_HIGHTLIGHT = new Paint(
|
||||
Paint.ANTI_ALIAS_FLAG);
|
||||
private static final double STROKE_INCREASE = 1.5;
|
||||
private static final byte STROKE_MIN_ZOOM_LEVEL = 12;
|
||||
|
||||
private static final byte ZOOM_MAX = 22;
|
||||
|
||||
// private static MapRenderer mMapRenderer;
|
||||
|
||||
private static RenderTheme getRenderTheme(JobTheme jobTheme) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = jobTheme.getRenderThemeAsStream();
|
||||
return RenderThemeHandler.getRenderTheme(inputStream);
|
||||
} catch (ParserConfigurationException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} catch (SAXException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static byte getValidLayer(byte layer) {
|
||||
if (layer < 0) {
|
||||
return 0;
|
||||
@ -103,7 +65,7 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
private List<PointTextContainer> mNodes;
|
||||
private float mPoiX;
|
||||
private float mPoiY;
|
||||
private JobTheme mPreviousJobTheme;
|
||||
private Theme mPreviousJobTheme;
|
||||
private float mPreviousTextScale;
|
||||
private byte mPreviousZoomLevel;
|
||||
private static RenderTheme renderTheme;
|
||||
@ -138,7 +100,7 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
/**
|
||||
* Constructs a new DatabaseRenderer.
|
||||
*/
|
||||
public DatabaseRenderer() {
|
||||
public MapGenerator() {
|
||||
mCanvasRasterer = new CanvasRasterer();
|
||||
mLabelPlacement = new LabelPlacement();
|
||||
|
||||
@ -161,8 +123,8 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
@Override
|
||||
public void cleanup() {
|
||||
mTileBitmap.recycle();
|
||||
if (DatabaseRenderer.renderTheme != null) {
|
||||
DatabaseRenderer.renderTheme.destroy();
|
||||
if (MapGenerator.renderTheme != null) {
|
||||
MapGenerator.renderTheme.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,30 +151,30 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
// mTileHeight = mLat1 - mLat2;
|
||||
mScale = mapGeneratorJob.getScale();
|
||||
|
||||
JobTheme jobTheme = mapGeneratorJob.jobParameters.jobTheme;
|
||||
if (!jobTheme.equals(mPreviousJobTheme)) {
|
||||
if (DatabaseRenderer.renderTheme == null)
|
||||
DatabaseRenderer.renderTheme = getRenderTheme(jobTheme);
|
||||
if (DatabaseRenderer.renderTheme == null) {
|
||||
mPreviousJobTheme = null;
|
||||
return false;
|
||||
}
|
||||
createWayLists();
|
||||
mPreviousJobTheme = jobTheme;
|
||||
mPreviousZoomLevel = Byte.MIN_VALUE;
|
||||
}
|
||||
|
||||
byte zoomLevel = mCurrentTile.zoomLevel;
|
||||
if (zoomLevel != mPreviousZoomLevel) {
|
||||
setScaleStrokeWidth(zoomLevel);
|
||||
mPreviousZoomLevel = zoomLevel;
|
||||
}
|
||||
|
||||
float textScale = mapGeneratorJob.jobParameters.textScale;
|
||||
if (textScale != mPreviousTextScale) {
|
||||
DatabaseRenderer.renderTheme.scaleTextSize(textScale);
|
||||
mPreviousTextScale = textScale;
|
||||
}
|
||||
// Theme theme = mapGeneratorJob.jobParameters.theme;
|
||||
// if (!theme.equals(mPreviousJobTheme)) {
|
||||
// // if (MapGenerator.renderTheme == null)
|
||||
// // MapGenerator.renderTheme = getRenderTheme(theme);
|
||||
// // if (MapGenerator.renderTheme == null) {
|
||||
// // mPreviousJobTheme = null;
|
||||
// // return false;
|
||||
// // }
|
||||
// createWayLists();
|
||||
// mPreviousJobTheme = theme;
|
||||
// mPreviousZoomLevel = Byte.MIN_VALUE;
|
||||
// }
|
||||
//
|
||||
// byte zoomLevel = mCurrentTile.zoomLevel;
|
||||
// if (zoomLevel != mPreviousZoomLevel) {
|
||||
// setScaleStrokeWidth(zoomLevel);
|
||||
// mPreviousZoomLevel = zoomLevel;
|
||||
// }
|
||||
//
|
||||
// float textScale = mapGeneratorJob.jobParameters.textScale;
|
||||
// if (textScale != mPreviousTextScale) {
|
||||
// MapGenerator.renderTheme.scaleTextSize(textScale);
|
||||
// mPreviousTextScale = textScale;
|
||||
// }
|
||||
|
||||
if (mMapDatabase != null) {
|
||||
mMapDatabase.executeQuery(mCurrentTile, this);
|
||||
@ -230,7 +192,7 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
// FIXME mCoords = mMapDatabase.getCoordinates();
|
||||
|
||||
mCanvasRasterer.setCanvasBitmap(mTileBitmap, mScale);
|
||||
mCanvasRasterer.fill(DatabaseRenderer.renderTheme.getMapBackground());
|
||||
mCanvasRasterer.fill(MapGenerator.renderTheme.getMapBackground());
|
||||
mCanvasRasterer.drawWays(mCoords, mWays);
|
||||
mCanvasRasterer.drawSymbols(mWaySymbols);
|
||||
mCanvasRasterer.drawSymbols(mPointSymbols);
|
||||
@ -255,37 +217,6 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeoPoint getStartPoint() {
|
||||
if (mMapDatabase != null && mMapDatabase.hasOpenFile()) {
|
||||
MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo();
|
||||
if (mapFileInfo.startPosition != null) {
|
||||
return mapFileInfo.startPosition;
|
||||
} else if (mapFileInfo.mapCenter != null) {
|
||||
return mapFileInfo.mapCenter;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte getStartZoomLevel() {
|
||||
if (mMapDatabase != null && mMapDatabase.hasOpenFile()) {
|
||||
MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo();
|
||||
if (mapFileInfo.startZoomLevel != null) {
|
||||
return mapFileInfo.startZoomLevel;
|
||||
}
|
||||
}
|
||||
|
||||
return DEFAULT_START_ZOOM_LEVEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getZoomLevelMax() {
|
||||
return ZOOM_MAX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderAreaCaption(String textKey, float verticalOffset, Paint paint,
|
||||
Paint stroke) {
|
||||
@ -314,7 +245,7 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
mDrawingLayer = mWays[getValidLayer(layer)];
|
||||
mPoiX = scaleLongitude(longitude);
|
||||
mPoiY = scaleLatitude(latitude);
|
||||
DatabaseRenderer.renderTheme.matchNode(this, tags, mCurrentTile.zoomLevel);
|
||||
MapGenerator.renderTheme.matchNode(this, tags, mCurrentTile.zoomLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -539,7 +470,7 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
}
|
||||
|
||||
private void createWayLists() {
|
||||
int levels = DatabaseRenderer.renderTheme.getLevels();
|
||||
int levels = MapGenerator.renderTheme.getLevels();
|
||||
for (byte i = LAYERS - 1; i >= 0; --i) {
|
||||
mWays[i] = new LayerContainer(levels);
|
||||
}
|
||||
@ -581,12 +512,18 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback,
|
||||
*/
|
||||
private static void setScaleStrokeWidth(byte zoomLevel) {
|
||||
int zoomLevelDiff = Math.max(zoomLevel - STROKE_MIN_ZOOM_LEVEL, 0);
|
||||
DatabaseRenderer.renderTheme.scaleStrokeWidth((float) Math.pow(STROKE_INCREASE,
|
||||
MapGenerator.renderTheme.scaleStrokeWidth((float) Math.pow(STROKE_INCREASE,
|
||||
zoomLevelDiff));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapRenderer getMapRenderer(MapView mapView) {
|
||||
return new MapRenderer(mapView);
|
||||
public IMapDatabase getMapDatabase() {
|
||||
return mMapDatabase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderTheme(RenderTheme theme) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
@ -28,10 +28,9 @@ import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import org.mapsforge.android.DebugSettings;
|
||||
import org.mapsforge.android.MapView;
|
||||
import org.mapsforge.android.mapgenerator.JobParameters;
|
||||
import org.mapsforge.android.mapgenerator.IMapGenerator;
|
||||
import org.mapsforge.android.mapgenerator.JobParameters;
|
||||
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
|
||||
import org.mapsforge.android.mapgenerator.MapWorker;
|
||||
import org.mapsforge.android.mapgenerator.TileCacheKey;
|
||||
import org.mapsforge.android.mapgenerator.TileDistanceSort;
|
||||
import org.mapsforge.android.utils.GlUtils;
|
||||
@ -46,7 +45,7 @@ import android.opengl.Matrix;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
public class MapRenderer implements org.mapsforge.android.IMapRenderer {
|
||||
// private static String TAG = "MapRenderer";
|
||||
|
||||
private static final int FLOAT_SIZE_BYTES = 4;
|
||||
@ -72,7 +71,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
private ArrayList<MapGeneratorJob> mJobList;
|
||||
|
||||
ArrayList<Integer> mTextures;
|
||||
MapWorker mMapWorker;
|
||||
MapView mMapView;
|
||||
|
||||
GLMapTile[] currentTiles;
|
||||
@ -97,7 +95,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
*/
|
||||
public MapRenderer(MapView mapView) {
|
||||
mMapView = mapView;
|
||||
mMapWorker = mapView.getMapWorker();
|
||||
mDebugSettings = mapView.getDebugSettings();
|
||||
mMapScale = 1;
|
||||
|
||||
@ -133,7 +130,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
if (diff != 0)
|
||||
{
|
||||
float z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff);
|
||||
t.distance = (long) (Math.abs((t.tileX) * z - x) + Math.abs((t.tileY) * z - y));
|
||||
t.distance = (long) (Math.abs((t.tileX) * z - x) + Math.abs((t.tileY) * z
|
||||
- y));
|
||||
t.distance *= 2 * diff * diff;
|
||||
} else {
|
||||
t.distance = (Math.abs(t.tileX - x) + Math.abs(t.tileY - y));
|
||||
@ -160,7 +158,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
}
|
||||
if (t.hasTexture()) {
|
||||
synchronized (mTextures) {
|
||||
mTextures.add(new Integer(t.getTexture()));
|
||||
mTextures.add(Integer.valueOf(t.getTexture()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -184,7 +182,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
|
||||
mJobList.clear();
|
||||
|
||||
IMapGenerator mapGenerator = mMapView.getMapGenerator();
|
||||
// IMapGenerator mapGenerator = mMapView.getMapGenerator();
|
||||
|
||||
int tiles = 0;
|
||||
for (long tileY = tileTop - 1; tileY <= tileBottom + 1; tileY++) {
|
||||
for (long tileX = tileLeft - 1; tileX <= tileRight + 1; tileX++) {
|
||||
@ -216,13 +215,14 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
if (!tile.isDrawn || (tile.getScale() != scale)) {
|
||||
tile.isLoading = true;
|
||||
// approximation for TileScheduler
|
||||
if (tileY < tileTop || tileY > tileBottom || tileX < tileLeft || tileX > tileRight)
|
||||
if (tileY < tileTop || tileY > tileBottom || tileX < tileLeft
|
||||
|| tileX > tileRight)
|
||||
tile.isVisible = false;
|
||||
else
|
||||
tile.isVisible = true;
|
||||
|
||||
MapGeneratorJob job = new MapGeneratorJob(tile, mapGenerator,
|
||||
mJobParameter, mDebugSettings);
|
||||
MapGeneratorJob job = new MapGeneratorJob(tile, mJobParameter,
|
||||
mDebugSettings);
|
||||
job.setScale(scale);
|
||||
mJobList.add(job);
|
||||
}
|
||||
@ -243,10 +243,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
}
|
||||
|
||||
if (mJobList.size() > 0) {
|
||||
mMapView.getJobQueue().setJobs(mJobList);
|
||||
synchronized (mMapWorker) {
|
||||
mMapWorker.notify();
|
||||
}
|
||||
mMapView.addJobs(mJobList);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -262,10 +259,12 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
|
||||
mMapPosition = mMapView.getMapPosition().getMapPosition();
|
||||
|
||||
long x = (long) MercatorProjection.longitudeToPixelX(mMapPosition.geoPoint.getLongitude(),
|
||||
long x = (long) MercatorProjection.longitudeToPixelX(
|
||||
mMapPosition.geoPoint.getLongitude(),
|
||||
mMapPosition.zoomLevel);
|
||||
long y = (long) MercatorProjection
|
||||
.latitudeToPixelY(mMapPosition.geoPoint.getLatitude(), mMapPosition.zoomLevel);
|
||||
.latitudeToPixelY(mMapPosition.geoPoint.getLatitude(),
|
||||
mMapPosition.zoomLevel);
|
||||
|
||||
long tileX = MercatorProjection.pixelXToTileX(x, mMapPosition.zoomLevel);
|
||||
long tileY = MercatorProjection.pixelYToTileY(y, mMapPosition.zoomLevel);
|
||||
@ -345,7 +344,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
z = 1.0f / (1 << -diff);
|
||||
}
|
||||
drawX = MercatorProjection
|
||||
.longitudeToPixelX(mMapPosition.geoPoint.getLongitude(), tile.zoomLevel);
|
||||
.longitudeToPixelX(mMapPosition.geoPoint.getLongitude(),
|
||||
tile.zoomLevel);
|
||||
drawY = MercatorProjection
|
||||
.latitudeToPixelY(mMapPosition.geoPoint.getLatitude(), tile.zoomLevel);
|
||||
|
||||
@ -377,7 +377,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
|
||||
Matrix.setIdentityM(mMatrix, 0);
|
||||
// map tile GL coordinates to screen coordinates
|
||||
Matrix.scaleM(mMatrix, 0, 2.0f * (tileSize * z) / mWidth, 2.0f * (tileSize * z) / mHeight, 1);
|
||||
Matrix.scaleM(mMatrix, 0, 2.0f * (tileSize * z) / mWidth, 2.0f * (tileSize * z)
|
||||
/ mHeight, 1);
|
||||
|
||||
// scale tile
|
||||
Matrix.scaleM(mMatrix, 0, mapScale / z, mapScale / z, 1);
|
||||
@ -396,7 +397,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
|
||||
@Override
|
||||
public void onDrawFrame(GL10 glUnused) {
|
||||
boolean loadedTexture = false;
|
||||
// boolean loadedTexture = false;
|
||||
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
|
||||
GLES20.glClearColor(0.95f, 0.95f, 0.94f, 1.0f);
|
||||
// GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
|
||||
@ -437,14 +438,16 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
if (tile.getTexture() >= 0) {
|
||||
// reuse tile texture
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tile.getTexture());
|
||||
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mMapGeneratorJob.getBitmap());
|
||||
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
|
||||
mMapGeneratorJob.getBitmap());
|
||||
} else if (mTextures.size() > 0) {
|
||||
// reuse texture from previous tiles
|
||||
Integer texture;
|
||||
texture = mTextures.remove(mTextures.size() - 1);
|
||||
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture.intValue());
|
||||
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mMapGeneratorJob.getBitmap());
|
||||
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
|
||||
mMapGeneratorJob.getBitmap());
|
||||
tile.setTexture(texture.intValue());
|
||||
} else {
|
||||
// create texture
|
||||
@ -457,7 +460,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
|
||||
mMapGeneratorJob = null;
|
||||
processedTile = true;
|
||||
loadedTexture = true;
|
||||
// loadedTexture = true;
|
||||
}
|
||||
int tileSize = (int) (Tile.TILE_SIZE * mMapScale);
|
||||
int hWidth = mWidth >> 1;
|
||||
@ -491,11 +494,12 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (loadedTexture) {
|
||||
synchronized (mMapWorker) {
|
||||
mMapWorker.notify();
|
||||
}
|
||||
}
|
||||
// FIXME
|
||||
// if (loadedTexture) {
|
||||
// synchronized (mMapWorker) {
|
||||
// mMapWorker.notify();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -579,65 +583,9 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
|
||||
public boolean processedTile() {
|
||||
return processedTile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMapGenerator createMapGenerator() {
|
||||
return new MapGenerator();
|
||||
}
|
||||
}
|
||||
|
||||
// private void limitCache(long top, long bottom, long left, long right, byte zoom, int remove) {
|
||||
// int cnt = 0;
|
||||
// TileCacheKey[] keys = new TileCacheKey[remove];
|
||||
//
|
||||
// for (Entry<TileCacheKey, GLMapTile> e : mTiles.entrySet()) {
|
||||
// GLMapTile t = e.getValue();
|
||||
// if (t.zoomLevel == zoom && t.tileX >= left && t.tileX <= right &&
|
||||
// t.tileY >= top && t.tileY <= bottom)
|
||||
// continue;
|
||||
//
|
||||
// if (t.zoomLevel + 1 == zoom) {
|
||||
// boolean found = false;
|
||||
// for (int i = 0; i < 4; i++) {
|
||||
// GLMapTile c = t.child[i];
|
||||
// if (c != null && !c.hasTexture() && c.tileX >= left && c.tileX <= right &&
|
||||
// c.tileY >= top && c.tileY <= bottom) {
|
||||
// found = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (found)
|
||||
// continue;
|
||||
// }
|
||||
// if (t.zoomLevel - 1 == zoom) {
|
||||
// GLMapTile p = t.parent;
|
||||
// if (p != null && !p.hasTexture() && p.tileX >= left && p.tileX <= right &&
|
||||
// p.tileY >= top && p.tileY <= bottom) {
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// keys[cnt++] = e.getKey();
|
||||
//
|
||||
// if (cnt == remove)
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// for (TileCacheKey key : keys) {
|
||||
// GLMapTile t = mTiles.remove(key);
|
||||
// if (t == null)
|
||||
// continue;
|
||||
//
|
||||
// for (int i = 0; i < 4; i++) {
|
||||
// if (t.child[i] != null)
|
||||
// t.child[i].parent = null;
|
||||
// }
|
||||
// if (t.parent != null) {
|
||||
// for (int i = 0; i < 4; i++) {
|
||||
// if (t.parent.child[i] == t)
|
||||
// t.parent.child[i] = null;
|
||||
// }
|
||||
// }
|
||||
// if (t.hasTexture()) {
|
||||
// synchronized (mTextures) {
|
||||
// mTextures.add(new Integer(t.getTexture()));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
@ -99,7 +99,7 @@ final class WayDecorator {
|
||||
}
|
||||
}
|
||||
|
||||
static void renderText(DatabaseRenderer databaseRenderer, Paint paint, Paint outline,
|
||||
static void renderText(MapGenerator mapGenerator, Paint paint, Paint outline,
|
||||
float[] coordinates, WayDataContainer wayDataContainer,
|
||||
List<WayTextContainer> wayNames) {
|
||||
|
||||
@ -185,7 +185,7 @@ final class WayDecorator {
|
||||
|
||||
if (wayNameWidth < 0) {
|
||||
if (text == null) {
|
||||
text = databaseRenderer.getWayName();
|
||||
text = mapGenerator.getWayName();
|
||||
if (text == null)
|
||||
text = "blub";
|
||||
}
|
||||
|
||||
@ -40,13 +40,17 @@ public class GlUtils {
|
||||
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
|
||||
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
|
||||
GLES20.GL_LINEAR);
|
||||
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
|
||||
GLES20.GL_LINEAR);
|
||||
|
||||
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
|
||||
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
|
||||
GLES20.GL_CLAMP_TO_EDGE);
|
||||
|
||||
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
|
||||
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
|
||||
GLES20.GL_CLAMP_TO_EDGE);
|
||||
|
||||
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
|
||||
|
||||
@ -125,4 +129,16 @@ public class GlUtils {
|
||||
// throw new RuntimeException(op + ": glError " + error);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean checkGlOutOfMemory(String op) {
|
||||
int error;
|
||||
boolean oom = false;
|
||||
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
|
||||
Log.e(TAG, op + ": glError " + error);
|
||||
// throw new RuntimeException(op + ": glError " + error);
|
||||
if (error == 1285)
|
||||
oom = true;
|
||||
}
|
||||
return oom;
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +37,14 @@ public abstract class PausableThread extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interrupt() {
|
||||
// first acquire the monitor which is used to call wait()
|
||||
synchronized (this) {
|
||||
super.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this thread is currently pausing, false otherwise.
|
||||
*/
|
||||
|
||||
@ -9,8 +9,7 @@ import org.mapsforge.android.DebugSettings;
|
||||
import org.mapsforge.android.MapActivity;
|
||||
import org.mapsforge.android.MapController;
|
||||
import org.mapsforge.android.MapView;
|
||||
import org.mapsforge.android.mapgenerator.MapDatabaseFactory;
|
||||
import org.mapsforge.android.mapgenerator.MapDatabaseInternal;
|
||||
import org.mapsforge.android.mapgenerator.MapDatabases;
|
||||
import org.mapsforge.android.rendertheme.InternalRenderTheme;
|
||||
import org.mapsforge.android.utils.AndroidUtils;
|
||||
import org.mapsforge.app.filefilter.FilterByFileExtension;
|
||||
@ -20,7 +19,6 @@ import org.mapsforge.app.filepicker.FilePicker;
|
||||
import org.mapsforge.app.preferences.EditPreferences;
|
||||
import org.mapsforge.core.BoundingBox;
|
||||
import org.mapsforge.core.GeoPoint;
|
||||
import org.mapsforge.database.IMapDatabase;
|
||||
import org.mapsforge.database.MapFileInfo;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
@ -74,7 +72,7 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
|
||||
private static final int SELECT_MAP_FILE = 0;
|
||||
private static final int SELECT_RENDER_THEME_FILE = 1;
|
||||
private LocationManager mLocationManager;
|
||||
private MapDatabaseInternal mMapDatabaseInternal;
|
||||
private MapDatabases mMapDatabase;
|
||||
private MyLocationListener mMyLocationListener;
|
||||
private boolean mShowMyLocation;
|
||||
private boolean mSnapToLocation;
|
||||
@ -88,8 +86,11 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.options_menu, menu);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
||||
getMenuInflater().inflate(R.menu.options_menu, menu);
|
||||
else
|
||||
getMenuInflater().inflate(R.menu.options_menu_pre_honeycomb, menu);
|
||||
mMenu = menu;
|
||||
return true;
|
||||
}
|
||||
@ -434,7 +435,7 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
|
||||
editText.setText(Double.toString(mapCenter.getLongitude()));
|
||||
|
||||
SeekBar zoomlevel = (SeekBar) dialog.findViewById(R.id.zoomLevel);
|
||||
zoomlevel.setMax(mMapView.getMapGenerator().getZoomLevelMax());
|
||||
zoomlevel.setMax(20); // FIXME mMapView.getMapGenerator().getZoomLevelMax());
|
||||
zoomlevel.setProgress(mMapView.getMapPosition().getZoomLevel());
|
||||
|
||||
final TextView textView = (TextView) dialog.findViewById(R.id.zoomlevelValue);
|
||||
@ -532,25 +533,31 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
|
||||
|
||||
if (preferences.contains("mapDatabase")) {
|
||||
String name = preferences.getString("mapDatabase",
|
||||
MapDatabaseInternal.POSTGIS_READER.name());
|
||||
MapDatabases.POSTGIS_READER.name());
|
||||
|
||||
MapDatabaseInternal mapDatabaseInternalNew;
|
||||
MapDatabases mapDatabaseNew;
|
||||
|
||||
try {
|
||||
mapDatabaseInternalNew = MapDatabaseInternal.valueOf(name);
|
||||
mapDatabaseNew = MapDatabases.valueOf(name);
|
||||
} catch (IllegalArgumentException e) {
|
||||
mapDatabaseInternalNew = MapDatabaseInternal.POSTGIS_READER;
|
||||
mapDatabaseNew = MapDatabases.POSTGIS_READER;
|
||||
}
|
||||
|
||||
// mapDatabaseInternalNew = MapDatabaseInternal.JSON_READER;
|
||||
Log.d("VectorTileMap", "set map database " + mapDatabaseInternalNew);
|
||||
// mapDatabaseInternalNew = MapDatabaseInternal.PBMAP_READER;
|
||||
Log.d("VectorTileMap", "set map database " + mapDatabaseNew);
|
||||
|
||||
if (mapDatabaseInternalNew != mMapDatabaseInternal) {
|
||||
IMapDatabase mapDatabase = MapDatabaseFactory
|
||||
.createMapDatabase(mapDatabaseInternalNew);
|
||||
mMapView.setMapDatabase(mapDatabase);
|
||||
mMapDatabaseInternal = mapDatabaseInternalNew;
|
||||
if (mapDatabaseNew != mMapDatabase) {
|
||||
mMapView.setMapDatabase(mapDatabaseNew);
|
||||
mMapDatabase = mapDatabaseNew;
|
||||
}
|
||||
|
||||
// if (mapDatabaseNew != mMapDatabase) {
|
||||
// IMapDatabase mapDatabase = MapDatabaseFactory
|
||||
// .createMapDatabase(mapDatabaseNew);
|
||||
//
|
||||
// mMapView.setMapDatabase(mapDatabase);
|
||||
// mMapDatabase = mapDatabaseNew;
|
||||
// }
|
||||
}
|
||||
|
||||
try {
|
||||
@ -586,7 +593,7 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL
|
||||
|
||||
mMapView.setDebugSettings(debugSettings);
|
||||
|
||||
if (mMapDatabaseInternal == MapDatabaseInternal.MAP_READER) {
|
||||
if (mMapDatabase == MapDatabases.MAP_READER) {
|
||||
if (mMapView.getMapFile() == null)
|
||||
startMapFilePicker();
|
||||
} else {
|
||||
|
||||
@ -226,7 +226,8 @@ public class FilePicker extends Activity implements AdapterView.OnItemClickListe
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
getActionBar().hide();
|
||||
// getActionBar().hide();
|
||||
|
||||
// check if the full screen mode should be activated
|
||||
// if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fullscreen", false)) {
|
||||
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
|
||||
@ -18,8 +18,6 @@ import org.mapsforge.app.R;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.WindowManager;
|
||||
|
||||
/**
|
||||
* Activity to edit the application preferences.
|
||||
@ -34,16 +32,16 @@ public class EditPreferences extends PreferenceActivity {
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
getActionBar().hide();
|
||||
// getActionBar().hide();
|
||||
|
||||
// check if the full screen mode should be activated
|
||||
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fullscreen",
|
||||
false)) {
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
||||
} else {
|
||||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
||||
}
|
||||
// if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fullscreen",
|
||||
// false)) {
|
||||
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
// getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
||||
// } else {
|
||||
// getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,6 +62,8 @@ public interface IMapDatabase {
|
||||
*/
|
||||
public abstract FileOpenResult openFile(File mapFile);
|
||||
|
||||
public abstract String getMapProjection();
|
||||
|
||||
/**
|
||||
* @param position
|
||||
* ....
|
||||
@ -69,4 +71,4 @@ public interface IMapDatabase {
|
||||
*/
|
||||
public abstract String readString(int position);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,13 +31,14 @@ import org.mapsforge.database.MapFileInfo;
|
||||
*/
|
||||
public class MapDatabase implements IMapDatabase {
|
||||
|
||||
private final static String PROJECTION = "Mercator";
|
||||
private float[] mCoords = new float[20];
|
||||
private int[] mIndex = new int[1];
|
||||
private int[] mIndex = new int[2];
|
||||
// private Tag[] mTags = { new Tag("boundary", "administrative"), new Tag("admin_level", "2") };
|
||||
private Tag[] mTags = { new Tag("building", "yes") };
|
||||
private Tag[] mTags = { new Tag("natural", "water") };
|
||||
private final MapFileInfo mMapInfo =
|
||||
new MapFileInfo(new BoundingBox(-180, -90, 180, 90),
|
||||
new Byte((byte) 0), null, "Mercator", 0, 0, 0, "de", "yo!", "by me");
|
||||
new Byte((byte) 0), null, PROJECTION, 0, 0, 0, "de", "yo!", "by me");
|
||||
|
||||
private boolean mOpenFile = false;
|
||||
|
||||
@ -95,10 +96,10 @@ public class MapDatabase implements IMapDatabase {
|
||||
//
|
||||
// mIndex[0] = 10;
|
||||
|
||||
lon1 = (float) MercatorProjection.pixelXToLongitude(cx - 80, tile.zoomLevel) * 1000000;
|
||||
lon2 = (float) MercatorProjection.pixelXToLongitude(cx + 80, tile.zoomLevel) * 1000000;
|
||||
lat1 = (float) MercatorProjection.pixelYToLatitude(cy - 80, tile.zoomLevel) * 1000000;
|
||||
lat2 = (float) MercatorProjection.pixelYToLatitude(cy + 80, tile.zoomLevel) * 1000000;
|
||||
lon1 = (float) MercatorProjection.pixelXToLongitude(cx - 139, tile.zoomLevel) * 1000000;
|
||||
lon2 = (float) MercatorProjection.pixelXToLongitude(cx + 139, tile.zoomLevel) * 1000000;
|
||||
lat1 = (float) MercatorProjection.pixelYToLatitude(cy - 139, tile.zoomLevel) * 1000000;
|
||||
lat2 = (float) MercatorProjection.pixelYToLatitude(cy + 139, tile.zoomLevel) * 1000000;
|
||||
|
||||
mCoords[0] = lon1;
|
||||
mCoords[1] = lat1;
|
||||
@ -117,9 +118,35 @@ public class MapDatabase implements IMapDatabase {
|
||||
|
||||
mIndex[0] = 10;
|
||||
|
||||
lon1 = (float) MercatorProjection.pixelXToLongitude(cx - 119, tile.zoomLevel) * 1000000;
|
||||
lon2 = (float) MercatorProjection.pixelXToLongitude(cx + 119, tile.zoomLevel) * 1000000;
|
||||
lat1 = (float) MercatorProjection.pixelYToLatitude(cy - 119, tile.zoomLevel) * 1000000;
|
||||
lat2 = (float) MercatorProjection.pixelYToLatitude(cy + 119, tile.zoomLevel) * 1000000;
|
||||
|
||||
mCoords[10] = lon1;
|
||||
mCoords[11] = lat1;
|
||||
|
||||
mCoords[12] = lon2;
|
||||
mCoords[13] = lat1;
|
||||
|
||||
mCoords[14] = lon2;
|
||||
mCoords[15] = lat2;
|
||||
|
||||
mCoords[16] = lon1;
|
||||
mCoords[17] = lat2;
|
||||
|
||||
mCoords[18] = lon1;
|
||||
mCoords[19] = lat1;
|
||||
|
||||
mIndex[1] = 10;
|
||||
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, mIndex, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMapProjection() {
|
||||
return PROJECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapFileInfo getMapFileInfo() {
|
||||
return mMapInfo;
|
||||
|
||||
@ -177,11 +177,13 @@ public class MapDatabase implements IMapDatabase {
|
||||
*/
|
||||
private static final int WAY_NUMBER_OF_TAGS_BITMASK = 0x0f;
|
||||
|
||||
private IndexCache mDatabaseIndexCache;
|
||||
private static IndexCache sDatabaseIndexCache;
|
||||
private static MapFileHeader sMapFileHeader;
|
||||
private static int instances = 0;
|
||||
|
||||
private long mFileSize;
|
||||
private boolean mDebugFile;
|
||||
private RandomAccessFile mInputFile;
|
||||
private MapFileHeader mMapFileHeader;
|
||||
private ReadBuffer mReadBuffer;
|
||||
private String mSignatureBlock;
|
||||
private String mSignaturePoi;
|
||||
@ -193,31 +195,6 @@ public class MapDatabase implements IMapDatabase {
|
||||
private float[] mWayNodes = new float[100000];
|
||||
private int mWayNodePosition;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.mapsforge.map.reader.IMapDatabase#closeFile()
|
||||
*/
|
||||
@Override
|
||||
public void closeFile() {
|
||||
try {
|
||||
mMapFileHeader = null;
|
||||
|
||||
if (mDatabaseIndexCache != null) {
|
||||
mDatabaseIndexCache.destroy();
|
||||
mDatabaseIndexCache = null;
|
||||
}
|
||||
|
||||
if (mInputFile != null) {
|
||||
mInputFile.close();
|
||||
mInputFile = null;
|
||||
}
|
||||
|
||||
mReadBuffer = null;
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.SEVERE, null, e);
|
||||
}
|
||||
}
|
||||
|
||||
private int minLat, minLon;
|
||||
|
||||
/*
|
||||
@ -227,7 +204,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
*/
|
||||
@Override
|
||||
public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
|
||||
if (mMapFileHeader == null)
|
||||
if (sMapFileHeader == null)
|
||||
return;
|
||||
|
||||
if (mIntBuffer == null)
|
||||
@ -235,29 +212,13 @@ public class MapDatabase implements IMapDatabase {
|
||||
|
||||
mWayNodePosition = 0;
|
||||
|
||||
// if (tile.zoomLevel < 10) {
|
||||
// // reduce small nodes with distance smaller min pixel
|
||||
// int min = 1;
|
||||
// long cx = tile.getPixelX() + (Tile.TILE_SIZE >> 1);
|
||||
// long cy = tile.getPixelY() + (Tile.TILE_SIZE >> 1);
|
||||
// double l1 = MercatorProjection.pixelXToLongitude(cx, tile.zoomLevel);
|
||||
// double l2 = MercatorProjection.pixelXToLongitude(cx + min, tile.zoomLevel);
|
||||
// minLon = (int) Math.abs((l1 * 1000000.0) - (l2 * 1000000.0));
|
||||
// l1 = MercatorProjection.pixelYToLatitude(cy, tile.zoomLevel);
|
||||
// l2 = MercatorProjection.pixelYToLatitude(cy + min, tile.zoomLevel);
|
||||
// minLat = (int) Math.abs((l1 * 1000000.0) - (l2 * 1000000.0));
|
||||
// } else {
|
||||
minLat = 0;
|
||||
minLon = 0;
|
||||
// }
|
||||
|
||||
try {
|
||||
prepareExecution();
|
||||
// prepareExecution();
|
||||
QueryParameters queryParameters = new QueryParameters();
|
||||
queryParameters.queryZoomLevel = mMapFileHeader
|
||||
queryParameters.queryZoomLevel = sMapFileHeader
|
||||
.getQueryZoomLevel(tile.zoomLevel);
|
||||
// get and check the sub-file for the query zoom level
|
||||
SubFileParameter subFileParameter = mMapFileHeader
|
||||
SubFileParameter subFileParameter = sMapFileHeader
|
||||
.getSubFileParameter(queryParameters.queryZoomLevel);
|
||||
if (subFileParameter == null) {
|
||||
LOG.warning("no sub-file for zoom level: "
|
||||
@ -279,10 +240,15 @@ public class MapDatabase implements IMapDatabase {
|
||||
*/
|
||||
@Override
|
||||
public MapFileInfo getMapFileInfo() {
|
||||
if (mMapFileHeader == null) {
|
||||
if (sMapFileHeader == null) {
|
||||
throw new IllegalStateException("no map file is currently opened");
|
||||
}
|
||||
return mMapFileHeader.getMapFileInfo();
|
||||
return sMapFileHeader.getMapFileInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMapProjection() {
|
||||
return getMapFileInfo().projectionName;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -300,6 +266,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
*/
|
||||
@Override
|
||||
public FileOpenResult openFile(File mapFile) {
|
||||
|
||||
try {
|
||||
if (mapFile == null) {
|
||||
// throw new IllegalArgumentException("mapFile must not be null");
|
||||
@ -323,14 +290,23 @@ public class MapDatabase implements IMapDatabase {
|
||||
mFileSize = mInputFile.length();
|
||||
mReadBuffer = new ReadBuffer(mInputFile);
|
||||
|
||||
mMapFileHeader = new MapFileHeader();
|
||||
FileOpenResult fileOpenResult = mMapFileHeader.readHeader(mReadBuffer,
|
||||
if (instances > 0) {
|
||||
instances++;
|
||||
return FileOpenResult.SUCCESS;
|
||||
}
|
||||
|
||||
sMapFileHeader = new MapFileHeader();
|
||||
FileOpenResult fileOpenResult = sMapFileHeader.readHeader(mReadBuffer,
|
||||
mFileSize);
|
||||
if (!fileOpenResult.isSuccess()) {
|
||||
closeFile();
|
||||
return fileOpenResult;
|
||||
}
|
||||
|
||||
prepareExecution();
|
||||
|
||||
instances++;
|
||||
|
||||
return FileOpenResult.SUCCESS;
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.SEVERE, null, e);
|
||||
@ -340,6 +316,37 @@ public class MapDatabase implements IMapDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.mapsforge.map.reader.IMapDatabase#closeFile()
|
||||
*/
|
||||
@Override
|
||||
public void closeFile() {
|
||||
instances--;
|
||||
if (instances > 0) {
|
||||
mReadBuffer = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
sMapFileHeader = null;
|
||||
|
||||
if (sDatabaseIndexCache != null) {
|
||||
sDatabaseIndexCache.destroy();
|
||||
sDatabaseIndexCache = null;
|
||||
}
|
||||
|
||||
if (mInputFile != null) {
|
||||
mInputFile.close();
|
||||
mInputFile = null;
|
||||
}
|
||||
|
||||
mReadBuffer = null;
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.SEVERE, null, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the debug signatures of the current way and block.
|
||||
*/
|
||||
@ -351,8 +358,8 @@ public class MapDatabase implements IMapDatabase {
|
||||
}
|
||||
|
||||
private void prepareExecution() {
|
||||
if (mDatabaseIndexCache == null) {
|
||||
mDatabaseIndexCache = new IndexCache(mInputFile, INDEX_CACHE_SIZE);
|
||||
if (sDatabaseIndexCache == null) {
|
||||
sDatabaseIndexCache = new IndexCache(mInputFile, INDEX_CACHE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,7 +443,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
long blockNumber = row * subFileParameter.blocksWidth + column;
|
||||
|
||||
// get the current index entry
|
||||
long currentBlockIndexEntry = mDatabaseIndexCache.getIndexEntry(
|
||||
long currentBlockIndexEntry = sDatabaseIndexCache.getIndexEntry(
|
||||
subFileParameter, blockNumber);
|
||||
|
||||
// check if the current query would still return a water tile
|
||||
@ -462,7 +469,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
nextBlockPointer = subFileParameter.subFileSize;
|
||||
} else {
|
||||
// get and check the next block pointer
|
||||
nextBlockPointer = mDatabaseIndexCache.getIndexEntry(
|
||||
nextBlockPointer = sDatabaseIndexCache.getIndexEntry(
|
||||
subFileParameter, blockNumber + 1)
|
||||
& BITMASK_INDEX_OFFSET;
|
||||
if (nextBlockPointer < 1
|
||||
@ -559,7 +566,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
* @return true if the POIs could be processed successfully, false otherwise.
|
||||
*/
|
||||
private boolean processPOIs(IMapDatabaseCallback mapDatabaseCallback, int numberOfPois) {
|
||||
Tag[] poiTags = mMapFileHeader.getMapFileInfo().poiTags;
|
||||
Tag[] poiTags = sMapFileHeader.getMapFileInfo().poiTags;
|
||||
Tag[] tags = null;
|
||||
|
||||
for (int elementCounter = numberOfPois; elementCounter != 0; --elementCounter) {
|
||||
@ -778,7 +785,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
int numberOfWays) {
|
||||
|
||||
Tag[] tags = null;
|
||||
Tag[] wayTags = mMapFileHeader.getMapFileInfo().wayTags;
|
||||
Tag[] wayTags = sMapFileHeader.getMapFileInfo().wayTags;
|
||||
int[] textPos = new int[3];
|
||||
// float[] labelPosition;
|
||||
boolean skippedWays = false;
|
||||
@ -957,7 +964,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
|| cumulatedNumberOfWays > MAXIMUM_ZOOM_TABLE_OBJECTS) {
|
||||
LOG.warning("invalid cumulated number of ways in row " + row + ' '
|
||||
+ cumulatedNumberOfWays);
|
||||
if (mMapFileHeader.getMapFileInfo().debugFile) {
|
||||
if (sMapFileHeader.getMapFileInfo().debugFile) {
|
||||
LOG.warning(DEBUG_SIGNATURE_BLOCK + mSignatureBlock);
|
||||
}
|
||||
return null;
|
||||
|
||||
513
src/org/mapsforge/database/pbmap/MapDatabase.java
Normal file
513
src/org/mapsforge/database/pbmap/MapDatabase.java
Normal file
@ -0,0 +1,513 @@
|
||||
/*
|
||||
* 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.database.pbmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.mapsforge.core.BoundingBox;
|
||||
import org.mapsforge.core.GeoPoint;
|
||||
import org.mapsforge.core.Tag;
|
||||
import org.mapsforge.core.Tile;
|
||||
import org.mapsforge.core.WebMercator;
|
||||
import org.mapsforge.database.FileOpenResult;
|
||||
import org.mapsforge.database.IMapDatabase;
|
||||
import org.mapsforge.database.IMapDatabaseCallback;
|
||||
import org.mapsforge.database.MapFileInfo;
|
||||
|
||||
import android.net.http.AndroidHttpClient;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class MapDatabase implements IMapDatabase {
|
||||
private static final String TAG = "MapDatabase";
|
||||
|
||||
private static final MapFileInfo mMapInfo =
|
||||
new MapFileInfo(new BoundingBox(-180, -90, 180, 90),
|
||||
new Byte((byte) 14), new GeoPoint(53.11, 8.85),
|
||||
WebMercator.NAME, 0, 0, 0, "de", "comment", "author");
|
||||
|
||||
private boolean mOpenFile = false;
|
||||
|
||||
// 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 Header encodingHeader =
|
||||
new BasicHeader("Accept-Encoding", "gzip");
|
||||
|
||||
private static volatile HashMap<String, Tag> tagHash = new HashMap<String, Tag>(100);
|
||||
|
||||
private Tag[] curTags = new Tag[1000];
|
||||
private int mCurTagCnt;
|
||||
|
||||
private AndroidHttpClient mClient;
|
||||
private IMapDatabaseCallback mMapGenerator;
|
||||
private float mScaleFactor;
|
||||
|
||||
@Override
|
||||
public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
|
||||
|
||||
String url = String.format(URL, Integer.valueOf(tile.zoomLevel),
|
||||
Long.valueOf(tile.tileX), Long.valueOf(tile.tileY));
|
||||
|
||||
HttpGet getRequest = new HttpGet(url);
|
||||
getRequest.addHeader(encodingHeader);
|
||||
mMapGenerator = mapDatabaseCallback;
|
||||
mCurTagCnt = 0;
|
||||
// using variable coordinate scalefactor to take advantage of
|
||||
// variable byte encoded integers
|
||||
mScaleFactor = 1 / 100f;
|
||||
if (tile.zoomLevel < 12)
|
||||
mScaleFactor = (float) Math.pow(2, (12 - tile.zoomLevel)) / 100f;
|
||||
|
||||
try {
|
||||
HttpResponse response = mClient.execute(getRequest);
|
||||
final int statusCode = response.getStatusLine().getStatusCode();
|
||||
if (statusCode != HttpStatus.SC_OK) {
|
||||
Log.d(TAG, "Http response " + statusCode);
|
||||
return;
|
||||
}
|
||||
|
||||
final HttpEntity entity = response.getEntity();
|
||||
if (entity == null) {
|
||||
Log.d(TAG, "Somethings wrong? - no entity " + statusCode);
|
||||
return;
|
||||
}
|
||||
|
||||
InputStream is = null;
|
||||
GZIPInputStream zis = null;
|
||||
try {
|
||||
|
||||
is = entity.getContent();
|
||||
zis = new GZIPInputStream(is);
|
||||
|
||||
decode(zis);
|
||||
|
||||
} finally {
|
||||
if (zis != null)
|
||||
zis.close();
|
||||
if (is != null)
|
||||
is.close();
|
||||
entity.consumeContent();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
getRequest.abort();
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMapProjection() {
|
||||
return WebMercator.NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapFileInfo getMapFileInfo() {
|
||||
return mMapInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOpenFile() {
|
||||
return mOpenFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileOpenResult openFile(File mapFile) {
|
||||
mOpenFile = true;
|
||||
mClient = AndroidHttpClient.newInstance("Android");
|
||||
return new FileOpenResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeFile() {
|
||||
mOpenFile = false;
|
||||
if (mClient != null)
|
||||
mClient.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readString(int position) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final int BUFFER_SIZE = 32768;
|
||||
private final byte[] buffer = new byte[BUFFER_SIZE];
|
||||
private int bufferPos;
|
||||
private int bufferSize;
|
||||
private InputStream inputStream;
|
||||
|
||||
private static final int TAG_TILE_TAGS = 1;
|
||||
private static final int TAG_TILE_WAYS = 2;
|
||||
private static final int TAG_TILE_NODES = 3;
|
||||
private static final int TAG_WAY_TAGS = 1;
|
||||
private static final int TAG_WAY_INDEX = 2;
|
||||
private static final int TAG_WAY_COORDS = 3;
|
||||
// private static final int TAG_NODE_TAGS = 1;
|
||||
// private static final int TAG_NODE_COORDS = 2;
|
||||
|
||||
private int bytesRead;
|
||||
|
||||
private boolean decode(InputStream is) throws IOException {
|
||||
inputStream = is;
|
||||
bytesRead = 0;
|
||||
bufferSize = 0;
|
||||
bufferPos = 0;
|
||||
while (true) {
|
||||
// read tag and wire type
|
||||
int val = decodeVarint32();
|
||||
if (val == 0) {
|
||||
// Log.d(TAG, "EOF, all good");
|
||||
return true;
|
||||
}
|
||||
int tag = (val >> 3);
|
||||
// int wireType = (val & 7);
|
||||
// Log.d(TAG, "tile " + tag + " " + wireType);
|
||||
|
||||
switch (tag) {
|
||||
case TAG_TILE_TAGS:
|
||||
decodeTileTags();
|
||||
break;
|
||||
|
||||
case TAG_TILE_WAYS:
|
||||
decodeTileWays();
|
||||
break;
|
||||
|
||||
case TAG_TILE_NODES:
|
||||
decodeTileNodes();
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.d(TAG, "invalid type for tile: " + tag);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean decodeTileTags() throws IOException {
|
||||
String tagString = decodeString();
|
||||
|
||||
Tag tag = tagHash.get(tagString);
|
||||
if (tag == null) {
|
||||
tag = new Tag(tagString);
|
||||
tagHash.put(tagString, tag);
|
||||
}
|
||||
curTags[mCurTagCnt++] = tag;
|
||||
|
||||
// Log.d(TAG, "tag:" + tag);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean decodeTileWays() throws IOException {
|
||||
int bytes = decodeVarint32();
|
||||
|
||||
int end = bytesRead + bytes;
|
||||
int indexCnt = 0;
|
||||
int tagCnt = 0;
|
||||
int coordCnt = 0;
|
||||
while (bytesRead < end) {
|
||||
// read tag and wire type
|
||||
|
||||
int val = decodeVarint32();
|
||||
if (val == 0)
|
||||
break;
|
||||
|
||||
int tag = (val >> 3);
|
||||
// int wireType = val & 7;
|
||||
|
||||
// Log.d(TAG, "way " + tag + " " + wireType + " bytes:" + bytes);
|
||||
|
||||
switch (tag) {
|
||||
case TAG_WAY_TAGS:
|
||||
tagCnt = decodeWayTags();
|
||||
break;
|
||||
|
||||
case TAG_WAY_INDEX:
|
||||
indexCnt = decodeWayIndices();
|
||||
break;
|
||||
|
||||
case TAG_WAY_COORDS:
|
||||
coordCnt = decodeWayCoordinates();
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.d(TAG, "invalid type for way: " + tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (indexCnt == 0 || tagCnt == 0)
|
||||
return false;
|
||||
|
||||
int[] index = new int[indexCnt];
|
||||
|
||||
int sum = 0;
|
||||
for (int i = 0; i < indexCnt; i++) {
|
||||
index[i] = tmpIndices[i] * 2;
|
||||
sum += index[i];
|
||||
}
|
||||
|
||||
Tag[] tags = new Tag[tagCnt];
|
||||
for (int i = 0; i < tagCnt; i++)
|
||||
tags[i] = curTags[tmpTags[i]];
|
||||
|
||||
float[] coords = tmpCoords;
|
||||
int pos = 0;
|
||||
|
||||
if (coordCnt != sum) {
|
||||
Log.d(TAG, "way length is wrong " + coordCnt + " " + sum);
|
||||
return false;
|
||||
}
|
||||
|
||||
float z = mScaleFactor;
|
||||
for (int j = 0, m = indexCnt; j < m; j++) {
|
||||
float lastX = 0;
|
||||
float lastY = 0;
|
||||
|
||||
for (int n = index[j] + pos; pos < n; pos += 2) {
|
||||
lastX = coords[pos] = (coords[pos] * z) + lastX;
|
||||
lastY = coords[pos + 1] = (coords[pos + 1] * z) + lastY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mMapGenerator.renderWay((byte) 0, tags, coords, index, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean decodeTileNodes() throws IOException {
|
||||
int bytes = decodeVarint32();
|
||||
Log.d(TAG, "way nodes " + bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
private int MAX_WAY_COORDS = 32768;
|
||||
private int MAX_WAY_INDICES = 1000;
|
||||
private int[] tmpTags = new int[32];
|
||||
private int[] tmpIndices = new int[MAX_WAY_INDICES];
|
||||
private float[] tmpCoords = new float[MAX_WAY_COORDS];
|
||||
|
||||
// private boolean ensureBufferSize(int size) throws IOException {
|
||||
// if (size > (bufferSize - bufferPos))
|
||||
// readBuffer(size - (bufferSize - bufferPos));
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
|
||||
private int decodeWayTags() throws IOException {
|
||||
int bytes = decodeVarint32();
|
||||
// Log.d(TAG, "way tags: " + bytes);
|
||||
|
||||
int cnt = 0;
|
||||
int end = bytesRead + bytes;
|
||||
|
||||
while (bytesRead < end)
|
||||
tmpTags[cnt++] = decodeVarint32();
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private int decodeWayIndices() throws IOException {
|
||||
int bytes = decodeVarint32();
|
||||
// Log.d(TAG, "way indices: " + bytes);
|
||||
|
||||
int cnt = 0;
|
||||
int end = bytesRead + bytes;
|
||||
|
||||
while (bytesRead < end) {
|
||||
int val = decodeVarint32();
|
||||
if (cnt >= MAX_WAY_INDICES) {
|
||||
|
||||
MAX_WAY_INDICES += 128;
|
||||
Log.d(TAG, "increase indices array " + MAX_WAY_INDICES);
|
||||
int[] tmp = new int[MAX_WAY_INDICES];
|
||||
System.arraycopy(tmpIndices, 0, tmp, 0, cnt);
|
||||
tmpIndices = tmp;
|
||||
}
|
||||
|
||||
tmpIndices[cnt++] = val;
|
||||
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private int decodeWayCoordinates() throws IOException {
|
||||
int bytes = decodeVarint32();
|
||||
|
||||
int cnt = 0;
|
||||
int end = bytesRead + bytes;
|
||||
|
||||
while (bytesRead < end) {
|
||||
int val = decodeZigZag32(decodeVarint32());
|
||||
if (cnt >= MAX_WAY_COORDS) {
|
||||
MAX_WAY_COORDS += 128;
|
||||
Log.d(TAG, "increase coords array " + MAX_WAY_COORDS);
|
||||
float[] tmp = new float[MAX_WAY_COORDS];
|
||||
System.arraycopy(tmpCoords, 0, tmp, 0, cnt);
|
||||
tmpCoords = tmp;
|
||||
}
|
||||
tmpCoords[cnt++] = val;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private void readBuffer() throws IOException {
|
||||
|
||||
int len = inputStream.read(buffer, 0, BUFFER_SIZE);
|
||||
if (len < 0) {
|
||||
buffer[bufferPos] = 0;
|
||||
// Log.d(TAG, " nothing to read... pos " + bufferPos + ", size "
|
||||
// + bufferSize + ", read " + bytesRead);
|
||||
return;
|
||||
}
|
||||
bufferSize = len;
|
||||
bufferPos = 0;
|
||||
|
||||
// Log.d(TAG, "pos " + bufferPos + ", size " + bufferSize + ", read "
|
||||
// + bytesRead);
|
||||
}
|
||||
|
||||
private void readBuffer(int size) throws IOException {
|
||||
if (size < (bufferSize - bufferPos))
|
||||
return;
|
||||
|
||||
if (size > BUFFER_SIZE) {
|
||||
Log.d(TAG, "EEEK too large");
|
||||
// FIXME throw exception, but frankly better sanitize tile data on compilation
|
||||
// this only happen with Strings larger than 32kb
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size - bufferSize) + bufferPos > BUFFER_SIZE) {
|
||||
// copy bytes left to read from buffer to the beginning of buffer
|
||||
System.arraycopy(buffer, bufferPos, buffer, 0, bufferSize - bufferPos);
|
||||
bufferPos = 0;
|
||||
}
|
||||
|
||||
while ((bufferSize - bufferPos) < size) {
|
||||
// read until requested size is available in buffer
|
||||
int len = inputStream.read(buffer, bufferSize, BUFFER_SIZE - bufferSize);
|
||||
if (len < 0) {
|
||||
buffer[bufferSize - 1] = 0; // FIXME is this needed?
|
||||
break;
|
||||
}
|
||||
bufferSize += len;
|
||||
}
|
||||
|
||||
// Log.d(TAG, "needed " + size + " pos " + bufferPos + ", size "
|
||||
// + bufferSize
|
||||
// + ", read " + bytesRead);
|
||||
}
|
||||
|
||||
/* All code below is taken from or based on Google's Protocol Buffers implementation: */
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
private byte readRawByte() throws IOException {
|
||||
if (bufferPos == bufferSize) {
|
||||
readBuffer();
|
||||
}
|
||||
bytesRead++;
|
||||
return buffer[bufferPos++];
|
||||
}
|
||||
|
||||
private int decodeVarint32() throws IOException {
|
||||
byte tmp = readRawByte();
|
||||
if (tmp >= 0) {
|
||||
return tmp;
|
||||
}
|
||||
int result = tmp & 0x7f;
|
||||
if ((tmp = readRawByte()) >= 0) {
|
||||
return result | tmp << 7;
|
||||
}
|
||||
result |= (tmp & 0x7f) << 7;
|
||||
if ((tmp = readRawByte()) >= 0) {
|
||||
return result | tmp << 14;
|
||||
}
|
||||
result |= (tmp & 0x7f) << 14;
|
||||
if ((tmp = readRawByte()) >= 0) {
|
||||
return result | tmp << 21;
|
||||
}
|
||||
result |= (tmp & 0x7f) << 21;
|
||||
result |= (tmp = readRawByte()) << 28;
|
||||
|
||||
if (tmp < 0) {
|
||||
// Discard upper 32 bits.
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (readRawByte() >= 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "EEK malformedVarint");
|
||||
// FIXME throw some poo
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private String decodeString() throws IOException {
|
||||
final int size = decodeVarint32();
|
||||
|
||||
readBuffer(size);
|
||||
|
||||
final String result = new String(buffer, bufferPos, size, "UTF-8");
|
||||
bufferPos += size;
|
||||
bytesRead += size;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
public static int decodeZigZag32(final int n) {
|
||||
return (n >>> 1) ^ -(n & 1);
|
||||
}
|
||||
|
||||
}
|
||||
@ -26,9 +26,9 @@ import java.util.Properties;
|
||||
|
||||
import org.mapsforge.core.BoundingBox;
|
||||
import org.mapsforge.core.GeoPoint;
|
||||
import org.mapsforge.core.WebMercator;
|
||||
import org.mapsforge.core.Tag;
|
||||
import org.mapsforge.core.Tile;
|
||||
import org.mapsforge.core.WebMercator;
|
||||
import org.mapsforge.database.FileOpenResult;
|
||||
import org.mapsforge.database.IMapDatabase;
|
||||
import org.mapsforge.database.IMapDatabaseCallback;
|
||||
@ -40,7 +40,7 @@ import org.postgresql.PGConnection;
|
||||
*
|
||||
*/
|
||||
public class MapDatabase implements IMapDatabase {
|
||||
private static final String QUERY = "SELECT * FROM __get_tile(?,?,?)";
|
||||
private static final String QUERY = "SELECT tags, geom FROM __get_tile(?,?,?)";
|
||||
|
||||
private final float mScale = 1; // 1000000.0f;
|
||||
|
||||
@ -55,16 +55,13 @@ public class MapDatabase implements IMapDatabase {
|
||||
new MapFileInfo(new BoundingBox(-180, -85, 180, 85),
|
||||
new Byte((byte) 14), new GeoPoint(53.11, 8.85),
|
||||
WebMercator.NAME,
|
||||
0, 0, 0, "de", "yo!", "hannes");
|
||||
// new MapFileInfo(new BoundingBox(-180, -90, 180, 90),
|
||||
// new Byte((byte) 0), null, "Mercator",
|
||||
// 0, 0, 0, "de", "yo!", "by me");
|
||||
0, 0, 0, "de", "comment", "author");
|
||||
|
||||
private boolean mOpenFile = false;
|
||||
|
||||
private Connection connection = null;
|
||||
private static HashMap<Entry<String, String>, Tag> tagHash = new HashMap<Entry<String, String>, Tag>(
|
||||
100);
|
||||
private static volatile HashMap<Entry<String, String>, Tag> tagHash =
|
||||
new HashMap<Entry<String, String>, Tag>(100);
|
||||
private PreparedStatement prepQuery = null;
|
||||
|
||||
private boolean connect() {
|
||||
@ -123,7 +120,6 @@ public class MapDatabase implements IMapDatabase {
|
||||
|
||||
byte[] b = null;
|
||||
PGHStore h = null;
|
||||
// long id;
|
||||
|
||||
try {
|
||||
while (r != null && r.next()) {
|
||||
@ -131,9 +127,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
mCoordPos = 0;
|
||||
|
||||
try {
|
||||
// id = r.getLong(1);
|
||||
|
||||
Object obj = r.getObject(2);
|
||||
Object obj = r.getObject(1);
|
||||
h = null;
|
||||
|
||||
if (obj instanceof PGHStore)
|
||||
@ -141,7 +135,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
else
|
||||
continue;
|
||||
|
||||
b = r.getBytes(3);
|
||||
b = r.getBytes(2);
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
@ -184,6 +178,11 @@ public class MapDatabase implements IMapDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMapProjection() {
|
||||
return WebMercator.NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapFileInfo getMapFileInfo() {
|
||||
return mMapInfo;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user