- remove swrenderer
- rearchitect: now that MapView is a ViewGroup and MapRenderer is the GLSurfaceView. - lock/unlock proxy tiles properly to not be removed from cache while in use
This commit is contained in:
parent
caea9cd7c9
commit
a1317a9de5
@ -8,7 +8,7 @@
|
|||||||
<org.oscim.view.MapView
|
<org.oscim.view.MapView
|
||||||
android:id="@+id/mapView"
|
android:id="@+id/mapView"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent" />
|
android:layout_height="fill_parent"/>
|
||||||
|
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
android:id="@+id/snapToLocationView"
|
android:id="@+id/snapToLocationView"
|
||||||
|
@ -6,7 +6,9 @@
|
|||||||
<!-- <item>MAP_READER</item> -->
|
<!-- <item>MAP_READER</item> -->
|
||||||
<!-- <item>POSTGIS_READER</item> -->
|
<!-- <item>POSTGIS_READER</item> -->
|
||||||
<item>PBMAP_READER</item>
|
<item>PBMAP_READER</item>
|
||||||
</string-array>
|
<!-- <item>OSCIMAP_READER</item> -->
|
||||||
|
<item>TEST_READER</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string name="preferences_map_database_default">PBMAP_READER</string>
|
<string name="preferences_map_database_default">PBMAP_READER</string>
|
||||||
|
|
||||||
|
@ -6,7 +6,9 @@
|
|||||||
<!-- <item>Mapfile</item> -->
|
<!-- <item>Mapfile</item> -->
|
||||||
<!-- <item>PostGIS</item> -->
|
<!-- <item>PostGIS</item> -->
|
||||||
<item>OpenScienceMap</item>
|
<item>OpenScienceMap</item>
|
||||||
</string-array>
|
<!-- <item>OpenScienceMap2</item> -->
|
||||||
|
<item>Test</item>
|
||||||
|
</string-array>
|
||||||
<string-array name="preferences_scale_bar_unit_values">
|
<string-array name="preferences_scale_bar_unit_values">
|
||||||
<item>Imperial</item>
|
<item>Imperial</item>
|
||||||
<item>Metric</item>
|
<item>Metric</item>
|
||||||
|
@ -12,10 +12,10 @@ import org.oscim.core.GeoPoint;
|
|||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.database.MapDatabases;
|
import org.oscim.database.MapDatabases;
|
||||||
import org.oscim.theme.InternalRenderTheme;
|
import org.oscim.theme.InternalRenderTheme;
|
||||||
|
import org.oscim.utils.AndroidUtils;
|
||||||
import org.oscim.view.DebugSettings;
|
import org.oscim.view.DebugSettings;
|
||||||
import org.oscim.view.MapActivity;
|
import org.oscim.view.MapActivity;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
import org.oscim.view.utils.AndroidUtils;
|
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.ActionBar;
|
import android.app.ActionBar;
|
||||||
@ -82,6 +82,7 @@ public class TileMap extends MapActivity {
|
|||||||
getMenuInflater().inflate(R.menu.options_menu, menu);
|
getMenuInflater().inflate(R.menu.options_menu, menu);
|
||||||
else
|
else
|
||||||
getMenuInflater().inflate(R.menu.options_menu_pre_honeycomb, menu);
|
getMenuInflater().inflate(R.menu.options_menu_pre_honeycomb, menu);
|
||||||
|
|
||||||
mMenu = menu;
|
mMenu = menu;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -100,30 +101,22 @@ public class TileMap extends MapActivity {
|
|||||||
|
|
||||||
case R.id.menu_rotation_enable:
|
case R.id.menu_rotation_enable:
|
||||||
mMapView.enableRotation(true);
|
mMapView.enableRotation(true);
|
||||||
toggleMenuRotation(mMenu,
|
toggleMenuRotation();
|
||||||
mMapView.enableRotation,
|
|
||||||
mMapView.enableCompass);
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case R.id.menu_rotation_disable:
|
case R.id.menu_rotation_disable:
|
||||||
mMapView.enableRotation(false);
|
mMapView.enableRotation(false);
|
||||||
toggleMenuRotation(mMenu,
|
toggleMenuRotation();
|
||||||
mMapView.enableRotation,
|
|
||||||
mMapView.enableCompass);
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case R.id.menu_compass_enable:
|
case R.id.menu_compass_enable:
|
||||||
mMapView.enableCompass(true);
|
mMapView.enableCompass(true);
|
||||||
toggleMenuRotation(mMenu,
|
toggleMenuRotation();
|
||||||
mMapView.enableRotation,
|
|
||||||
mMapView.enableCompass);
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case R.id.menu_compass_disable:
|
case R.id.menu_compass_disable:
|
||||||
mMapView.enableCompass(false);
|
mMapView.enableCompass(false);
|
||||||
toggleMenuRotation(mMenu,
|
toggleMenuRotation();
|
||||||
mMapView.enableRotation,
|
|
||||||
mMapView.enableCompass);
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case R.id.menu_position_my_location_enable:
|
case R.id.menu_position_my_location_enable:
|
||||||
@ -187,16 +180,17 @@ public class TileMap extends MapActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void toggleMenuRotation(Menu menu, boolean rotate, boolean compass) {
|
private void toggleMenuRotation() {
|
||||||
toggleMenuItem(menu,
|
|
||||||
|
toggleMenuItem(mMenu,
|
||||||
R.id.menu_rotation_enable,
|
R.id.menu_rotation_enable,
|
||||||
R.id.menu_rotation_disable,
|
R.id.menu_rotation_disable,
|
||||||
!rotate);
|
!mMapView.enableRotation);
|
||||||
|
|
||||||
toggleMenuItem(menu,
|
toggleMenuItem(mMenu,
|
||||||
R.id.menu_compass_enable,
|
R.id.menu_compass_enable,
|
||||||
R.id.menu_compass_disable,
|
R.id.menu_compass_disable,
|
||||||
!compass);
|
!mMapView.enableCompass);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void toggleMenuItem(Menu menu, int id, int id2, boolean enable) {
|
private static void toggleMenuItem(Menu menu, int id, int id2, boolean enable) {
|
||||||
@ -208,28 +202,17 @@ public class TileMap extends MapActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
menu.clear();
|
|
||||||
onCreateOptionsMenu(menu);
|
if (!isPreHoneyComb()) {
|
||||||
|
menu.clear();
|
||||||
|
onCreateOptionsMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
toggleMenuItem(menu,
|
toggleMenuItem(menu,
|
||||||
R.id.menu_position_my_location_enable,
|
R.id.menu_position_my_location_enable,
|
||||||
R.id.menu_position_my_location_disable,
|
R.id.menu_position_my_location_disable,
|
||||||
!mLocation.isShowMyLocationEnabled());
|
!mLocation.isShowMyLocationEnabled());
|
||||||
|
|
||||||
// if (mLocation.isShowMyLocationEnabled()) {
|
|
||||||
// menu.findItem(R.id.menu_position_my_location_enable).setVisible(false);
|
|
||||||
// menu.findItem(R.id.menu_position_my_location_enable).setEnabled(false);
|
|
||||||
// menu.findItem(R.id.menu_position_my_location_disable).setVisible(true);
|
|
||||||
// menu.findItem(R.id.menu_position_my_location_disable).setEnabled(true);
|
|
||||||
// } else {
|
|
||||||
// menu.findItem(R.id.menu_position_my_location_enable).setVisible(true);
|
|
||||||
// menu.findItem(R.id.menu_position_my_location_enable).setEnabled(true);
|
|
||||||
// menu.findItem(R.id.menu_position_my_location_disable).setVisible(false);
|
|
||||||
// menu.findItem(R.id.menu_position_my_location_disable).setEnabled(false);
|
|
||||||
// }
|
|
||||||
|
|
||||||
menu.findItem(R.id.menu_render_theme).setEnabled(true);
|
|
||||||
|
|
||||||
if (mMapDatabase == MapDatabases.MAP_READER) {
|
if (mMapDatabase == MapDatabases.MAP_READER) {
|
||||||
menu.findItem(R.id.menu_mapfile).setVisible(true);
|
menu.findItem(R.id.menu_mapfile).setVisible(true);
|
||||||
menu.findItem(R.id.menu_position_map_center).setVisible(true);
|
menu.findItem(R.id.menu_position_map_center).setVisible(true);
|
||||||
@ -238,15 +221,7 @@ public class TileMap extends MapActivity {
|
|||||||
menu.findItem(R.id.menu_position_map_center).setVisible(false);
|
menu.findItem(R.id.menu_position_map_center).setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleMenuItem(menu,
|
toggleMenuRotation();
|
||||||
R.id.menu_compass_enable,
|
|
||||||
R.id.menu_compass_disable,
|
|
||||||
!mMapView.enableCompass);
|
|
||||||
|
|
||||||
toggleMenuItem(mMenu,
|
|
||||||
R.id.menu_rotation_enable,
|
|
||||||
R.id.menu_rotation_disable,
|
|
||||||
!mMapView.enableRotation);
|
|
||||||
|
|
||||||
return super.onPrepareOptionsMenu(menu);
|
return super.onPrepareOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
@ -257,13 +232,6 @@ public class TileMap extends MapActivity {
|
|||||||
return mMapView.onTrackballEvent(event);
|
return mMapView.onTrackballEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureMapView() {
|
|
||||||
// configure the MapView and activate the zoomLevel buttons
|
|
||||||
mMapView.setClickable(true);
|
|
||||||
// mMapView.setBuiltInZoomControls(true);
|
|
||||||
mMapView.setFocusable(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startMapFilePicker() {
|
private void startMapFilePicker() {
|
||||||
FilePicker.setFileDisplayFilter(FILE_FILTER_EXTENSION_MAP);
|
FilePicker.setFileDisplayFilter(FILE_FILTER_EXTENSION_MAP);
|
||||||
FilePicker.setFileSelectFilter(new ValidMapFile());
|
FilePicker.setFileSelectFilter(new ValidMapFile());
|
||||||
@ -306,12 +274,16 @@ public class TileMap extends MapActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean isPreHoneyComb() {
|
||||||
|
return Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB;
|
||||||
|
}
|
||||||
|
|
||||||
@TargetApi(11)
|
@TargetApi(11)
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
if (!isPreHoneyComb()) {
|
||||||
mSpinnerAdapter = ArrayAdapter.createFromResource(this,
|
mSpinnerAdapter = ArrayAdapter.createFromResource(this,
|
||||||
R.array.view_sections,
|
R.array.view_sections,
|
||||||
android.R.layout.simple_spinner_dropdown_item);
|
android.R.layout.simple_spinner_dropdown_item);
|
||||||
@ -325,11 +297,12 @@ public class TileMap extends MapActivity {
|
|||||||
// set up the layout views
|
// set up the layout views
|
||||||
setContentView(R.layout.activity_tilemap);
|
setContentView(R.layout.activity_tilemap);
|
||||||
|
|
||||||
// getActionBar().setDisplayOptions(ActionBar.NAVIGATION_MODE_TABS);
|
|
||||||
|
|
||||||
mMapView = (MapView) findViewById(R.id.mapView);
|
mMapView = (MapView) findViewById(R.id.mapView);
|
||||||
|
|
||||||
configureMapView();
|
// configure the MapView and activate the zoomLevel buttons
|
||||||
|
mMapView.setClickable(true);
|
||||||
|
// mMapView.setBuiltInZoomControls(true);
|
||||||
|
mMapView.setFocusable(true);
|
||||||
|
|
||||||
mLocation = new LocationHandler(this);
|
mLocation = new LocationHandler(this);
|
||||||
|
|
||||||
@ -605,7 +578,6 @@ public class TileMap extends MapActivity {
|
|||||||
if (Build.VERSION.SDK_INT >= 11) {
|
if (Build.VERSION.SDK_INT >= 11) {
|
||||||
VersionHelper.refreshActionBarMenu(this);
|
VersionHelper.refreshActionBarMenu(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class VersionHelper {
|
static class VersionHelper {
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.core;
|
package org.oscim.core;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A GeoPoint represents an immutable pair of latitude and longitude coordinates.
|
* A GeoPoint represents an immutable pair of latitude and longitude coordinates.
|
||||||
*/
|
*/
|
||||||
@ -119,10 +118,10 @@ public class GeoPoint implements Comparable<GeoPoint> {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
stringBuilder.append("GeoPoint [latitudeE6=");
|
stringBuilder.append("GeoPoint [lat=");
|
||||||
stringBuilder.append(this.latitudeE6);
|
stringBuilder.append(this.getLatitude());
|
||||||
stringBuilder.append(", longitudeE6=");
|
stringBuilder.append(", lon=");
|
||||||
stringBuilder.append(this.longitudeE6);
|
stringBuilder.append(this.getLongitude());
|
||||||
stringBuilder.append("]");
|
stringBuilder.append("]");
|
||||||
return stringBuilder.toString();
|
return stringBuilder.toString();
|
||||||
}
|
}
|
||||||
|
@ -22,22 +22,22 @@ public class Tag {
|
|||||||
/**
|
/**
|
||||||
* The key of the house number OpenStreetMap tag.
|
* The key of the house number OpenStreetMap tag.
|
||||||
*/
|
*/
|
||||||
public static final String TAG_KEY_HOUSE_NUMBER = "addr:housenumber";
|
public static final String TAG_KEY_HOUSE_NUMBER = "addr:housenumber".intern();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key of the name OpenStreetMap tag.
|
* The key of the name OpenStreetMap tag.
|
||||||
*/
|
*/
|
||||||
public static final String TAG_KEY_NAME = "name";
|
public static final String TAG_KEY_NAME = "name".intern();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key of the reference OpenStreetMap tag.
|
* The key of the reference OpenStreetMap tag.
|
||||||
*/
|
*/
|
||||||
public static final String TAG_KEY_REF = "ref";
|
public static final String TAG_KEY_REF = "ref".intern();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key of the elevation OpenStreetMap tag.
|
* The key of the elevation OpenStreetMap tag.
|
||||||
*/
|
*/
|
||||||
public static final String TAG_KEY_ELE = "ele";
|
public static final String TAG_KEY_ELE = "ele".intern();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key of this tag.
|
* The key of this tag.
|
||||||
@ -102,8 +102,8 @@ public class Tag {
|
|||||||
this.value = (value == null ? null : value.intern());
|
this.value = (value == null ? null : value.intern());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.key = (key == null ? null : key);
|
this.key = key;
|
||||||
this.value = (value == null ? null : value);
|
this.value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ package org.oscim.database;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
import org.oscim.view.generator.JobTile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -26,14 +26,14 @@ public interface IMapDatabaseCallback {
|
|||||||
*
|
*
|
||||||
* @param layer
|
* @param layer
|
||||||
* the layer of the node.
|
* the layer of the node.
|
||||||
|
* @param tags
|
||||||
|
* the tags of the node.
|
||||||
* @param latitude
|
* @param latitude
|
||||||
* the latitude of the node.
|
* the latitude of the node.
|
||||||
* @param longitude
|
* @param longitude
|
||||||
* the longitude of the node.
|
* the longitude of the node.
|
||||||
* @param tags
|
|
||||||
* the tags of the node.
|
|
||||||
*/
|
*/
|
||||||
void renderPointOfInterest(byte layer, float latitude, float longitude, Tag[] tags);
|
void renderPointOfInterest(byte layer, Tag[] tags, float latitude, float longitude);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders water background for the current tile.
|
* Renders water background for the current tile.
|
||||||
@ -51,12 +51,21 @@ public interface IMapDatabaseCallback {
|
|||||||
* the geographical coordinates of the way nodes in the order longitude/latitude.
|
* the geographical coordinates of the way nodes in the order longitude/latitude.
|
||||||
* @param wayLength
|
* @param wayLength
|
||||||
* length of way data in wayNodes
|
* length of way data in wayNodes
|
||||||
* @param changed
|
* @param closed
|
||||||
* tags have changed since last call (just an optional hint)
|
* way is closed (means need to add endpoint == startpoint)
|
||||||
*/
|
*/
|
||||||
void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLength,
|
void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLength,
|
||||||
boolean changed);
|
boolean closed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TBD: check if way will be rendered before decoding
|
||||||
|
*
|
||||||
|
* @param tags
|
||||||
|
* ...
|
||||||
|
* @param closed
|
||||||
|
* ...
|
||||||
|
* @return true if the way will be rendered (i.e. found match in RenderTheme)
|
||||||
|
*/
|
||||||
boolean checkWay(Tag[] tags, boolean closed);
|
boolean checkWay(Tag[] tags, boolean closed);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.database;
|
package org.oscim.database;
|
||||||
|
|
||||||
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,6 +65,8 @@ public final class MapDatabaseFactory {
|
|||||||
return new org.oscim.database.postgis.MapDatabase();
|
return new org.oscim.database.postgis.MapDatabase();
|
||||||
case PBMAP_READER:
|
case PBMAP_READER:
|
||||||
return new org.oscim.database.pbmap.MapDatabase();
|
return new org.oscim.database.pbmap.MapDatabase();
|
||||||
|
case OSCIMAP_READER:
|
||||||
|
return new org.oscim.database.oscimap.MapDatabase();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,4 +37,8 @@ public enum MapDatabases {
|
|||||||
* ...
|
* ...
|
||||||
*/
|
*/
|
||||||
PBMAP_READER,
|
PBMAP_READER,
|
||||||
|
/**
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
OSCIMAP_READER,
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,8 @@ import java.util.Map;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.oscim.core.LRUCache;
|
|
||||||
import org.oscim.database.mapfile.header.SubFileParameter;
|
import org.oscim.database.mapfile.header.SubFileParameter;
|
||||||
|
import org.oscim.utils.LRUCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cache for database index blocks with a fixed size and LRU policy.
|
* A cache for database index blocks with a fixed size and LRU policy.
|
||||||
|
@ -30,7 +30,7 @@ import org.oscim.database.QueryResult;
|
|||||||
import org.oscim.database.mapfile.header.MapFileHeader;
|
import org.oscim.database.mapfile.header.MapFileHeader;
|
||||||
import org.oscim.database.mapfile.header.MapFileInfo;
|
import org.oscim.database.mapfile.header.MapFileInfo;
|
||||||
import org.oscim.database.mapfile.header.SubFileParameter;
|
import org.oscim.database.mapfile.header.SubFileParameter;
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
import org.oscim.view.generator.JobTile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class for reading binary map files.
|
* A class for reading binary map files.
|
||||||
@ -641,7 +641,7 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
// Integer.toString(mReadBuffer.readSignedInt())));
|
// Integer.toString(mReadBuffer.readSignedInt())));
|
||||||
}
|
}
|
||||||
|
|
||||||
mapDatabaseCallback.renderPointOfInterest(layer, latitude, longitude, tags);
|
mapDatabaseCallback.renderPointOfInterest(layer, tags, latitude, longitude);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1026
src/org/oscim/database/oscimap/MapDatabase.java
Normal file
1026
src/org/oscim/database/oscimap/MapDatabase.java
Normal file
File diff suppressed because it is too large
Load Diff
1282
src/org/oscim/database/oscimap/Tags.java
Normal file
1282
src/org/oscim/database/oscimap/Tags.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -62,7 +62,7 @@ import org.oscim.database.IMapDatabaseCallback;
|
|||||||
import org.oscim.database.MapInfo;
|
import org.oscim.database.MapInfo;
|
||||||
import org.oscim.database.OpenResult;
|
import org.oscim.database.OpenResult;
|
||||||
import org.oscim.database.QueryResult;
|
import org.oscim.database.QueryResult;
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
import org.oscim.view.generator.JobTile;
|
||||||
|
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
@ -604,7 +604,7 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
lastY = lat + lastY;
|
lastY = lat + lastY;
|
||||||
|
|
||||||
mMapGenerator.renderPointOfInterest(layer,
|
mMapGenerator.renderPointOfInterest(layer,
|
||||||
lastY / scale, lastX / scale, tags);
|
tags, lastY / scale, lastX / scale);
|
||||||
cnt += 2;
|
cnt += 2;
|
||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
|
@ -580,7 +580,7 @@ public class Tags {
|
|||||||
private static final String s_boutique = "boutique".intern();
|
private static final String s_boutique = "boutique".intern();
|
||||||
private static final String s_boat_storage = "boat_storage".intern();
|
private static final String s_boat_storage = "boat_storage".intern();
|
||||||
|
|
||||||
public final static Tag[] tags = {
|
public static final Tag[] tags = {
|
||||||
|
|
||||||
new Tag(s_building, s_yes, true), new Tag(s_highway, s_residential, true),
|
new Tag(s_building, s_yes, true), new Tag(s_highway, s_residential, true),
|
||||||
new Tag(s_highway, s_service, true), new Tag(s_waterway, s_stream, true),
|
new Tag(s_highway, s_service, true), new Tag(s_waterway, s_stream, true),
|
||||||
|
@ -33,7 +33,7 @@ import org.oscim.database.IMapDatabaseCallback;
|
|||||||
import org.oscim.database.MapInfo;
|
import org.oscim.database.MapInfo;
|
||||||
import org.oscim.database.OpenResult;
|
import org.oscim.database.OpenResult;
|
||||||
import org.oscim.database.QueryResult;
|
import org.oscim.database.QueryResult;
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
import org.oscim.view.generator.JobTile;
|
||||||
import org.postgresql.PGConnection;
|
import org.postgresql.PGConnection;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -176,8 +176,8 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
Log.d(TAG, "no index: skip way");
|
Log.d(TAG, "no index: skip way");
|
||||||
continue;
|
continue;
|
||||||
} else if (mIndexPos == 1) {
|
} else if (mIndexPos == 1) {
|
||||||
mapDatabaseCallback.renderPointOfInterest((byte) 0, mCoords[1],
|
mapDatabaseCallback.renderPointOfInterest((byte) 0, mTags,
|
||||||
mCoords[0], mTags);
|
mCoords[1], mCoords[0]);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
short[] idx = new short[mIndexPos];
|
short[] idx = new short[mIndexPos];
|
||||||
|
@ -17,7 +17,6 @@ package org.oscim.database.test;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.oscim.core.BoundingBox;
|
import org.oscim.core.BoundingBox;
|
||||||
import org.oscim.core.MercatorProjection;
|
|
||||||
import org.oscim.core.Tag;
|
import org.oscim.core.Tag;
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.database.IMapDatabase;
|
import org.oscim.database.IMapDatabase;
|
||||||
@ -25,7 +24,7 @@ import org.oscim.database.IMapDatabaseCallback;
|
|||||||
import org.oscim.database.MapInfo;
|
import org.oscim.database.MapInfo;
|
||||||
import org.oscim.database.OpenResult;
|
import org.oscim.database.OpenResult;
|
||||||
import org.oscim.database.QueryResult;
|
import org.oscim.database.QueryResult;
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
import org.oscim.view.generator.JobTile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -35,7 +34,7 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
|
|
||||||
private final static String PROJECTION = "Mercator";
|
private final static String PROJECTION = "Mercator";
|
||||||
private float[] mCoords = new float[20];
|
private float[] mCoords = new float[20];
|
||||||
private short[] mIndex = new short[2];
|
private short[] mIndex = new short[4];
|
||||||
// private Tag[] mTags = { new Tag("boundary", "administrative"), new Tag("admin_level", "2") };
|
// private Tag[] mTags = { new Tag("boundary", "administrative"), new Tag("admin_level", "2") };
|
||||||
private Tag[] mTags = { new Tag("natural", "water") };
|
private Tag[] mTags = { new Tag("natural", "water") };
|
||||||
private Tag[] mNameTags;
|
private Tag[] mNameTags;
|
||||||
@ -46,64 +45,13 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
|
|
||||||
private boolean mOpenFile = false;
|
private boolean mOpenFile = false;
|
||||||
|
|
||||||
// private static double radius = 6378137;
|
|
||||||
// private static double D2R = Math.PI / 180;
|
|
||||||
|
|
||||||
// private static double HALF_PI = Math.PI / 2;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
|
public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
|
||||||
|
|
||||||
long cx = tile.pixelX + (Tile.TILE_SIZE >> 1);
|
float lat1 = -0.5f;
|
||||||
long cy = tile.pixelY + (Tile.TILE_SIZE >> 1);
|
float lon1 = -0.5f;
|
||||||
// float lon1 = (float) MercatorProjection.pixelXToLongitude(cx - 100, tile.zoomLevel) * 1000000;
|
float lat2 = Tile.TILE_SIZE - 0.5f;
|
||||||
// float lon2 = (float) MercatorProjection.pixelXToLongitude(cx + 100, tile.zoomLevel) * 1000000;
|
float lon2 = Tile.TILE_SIZE - 0.5f;
|
||||||
// float lat1 = (float) MercatorProjection.pixelYToLatitude(cy - 100, tile.zoomLevel) * 1000000;
|
|
||||||
// float lat2 = (float) MercatorProjection.pixelYToLatitude(cy + 100, tile.zoomLevel) * 1000000;
|
|
||||||
|
|
||||||
float lon1 = (float) MercatorProjection.pixelXToLongitude(cx - 100,
|
|
||||||
tile.zoomLevel);
|
|
||||||
float lon2 = (float) MercatorProjection.pixelXToLongitude(cx + 100,
|
|
||||||
tile.zoomLevel);
|
|
||||||
float lat1 = (float) MercatorProjection
|
|
||||||
.pixelYToLatitude(cy - 100, tile.zoomLevel);
|
|
||||||
float lat2 = (float) MercatorProjection
|
|
||||||
.pixelYToLatitude(cy + 100, tile.zoomLevel);
|
|
||||||
|
|
||||||
// double lonRadians = (D2R * lon1);
|
|
||||||
// double latRadians = (D2R * lat1);
|
|
||||||
|
|
||||||
// spherical mercator projection
|
|
||||||
// lon1 = (float) (radius * lonRadians);
|
|
||||||
// lat1 = (float) (radius * Math.log(Math.tan(Math.PI * 0.25 + latRadians * 0.5)));
|
|
||||||
//
|
|
||||||
// lonRadians = (D2R * lon2);
|
|
||||||
// latRadians = (D2R * lat2);
|
|
||||||
//
|
|
||||||
// lon2 = (float) (radius * lonRadians);
|
|
||||||
// lat2 = (float) (radius * Math.log(Math.tan(Math.PI * 0.25 + latRadians * 0.5)));
|
|
||||||
//
|
|
||||||
// mCoords[0] = lon1;
|
|
||||||
// mCoords[1] = lat1;
|
|
||||||
//
|
|
||||||
// mCoords[2] = lon2;
|
|
||||||
// mCoords[3] = lat1;
|
|
||||||
//
|
|
||||||
// mCoords[4] = lon2;
|
|
||||||
// mCoords[5] = lat2;
|
|
||||||
//
|
|
||||||
// mCoords[6] = lon1;
|
|
||||||
// mCoords[7] = lat2;
|
|
||||||
//
|
|
||||||
// mCoords[8] = lon1;
|
|
||||||
// mCoords[9] = lat1;
|
|
||||||
//
|
|
||||||
// mIndex[0] = 10;
|
|
||||||
|
|
||||||
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[0] = lon1;
|
||||||
mCoords[1] = lat1;
|
mCoords[1] = lat1;
|
||||||
@ -120,12 +68,13 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
mCoords[8] = lon1;
|
mCoords[8] = lon1;
|
||||||
mCoords[9] = lat1;
|
mCoords[9] = lat1;
|
||||||
|
|
||||||
mIndex[0] = 10;
|
mIndex[0] = 8;
|
||||||
|
mIndex[1] = 2;
|
||||||
|
|
||||||
lon1 = (float) MercatorProjection.pixelXToLongitude(cx - 119, tile.zoomLevel) * 1000000;
|
lon1 = 40;
|
||||||
lon2 = (float) MercatorProjection.pixelXToLongitude(cx + 119, tile.zoomLevel) * 1000000;
|
lon2 = Tile.TILE_SIZE - 40;
|
||||||
lat1 = (float) MercatorProjection.pixelYToLatitude(cy - 119, tile.zoomLevel) * 1000000;
|
lat1 = 40;
|
||||||
lat2 = (float) MercatorProjection.pixelYToLatitude(cy + 119, tile.zoomLevel) * 1000000;
|
lat2 = Tile.TILE_SIZE - 40;
|
||||||
|
|
||||||
mCoords[10] = lon1;
|
mCoords[10] = lon1;
|
||||||
mCoords[11] = lat1;
|
mCoords[11] = lat1;
|
||||||
@ -142,24 +91,26 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
mCoords[18] = lon1;
|
mCoords[18] = lon1;
|
||||||
mCoords[19] = lat1;
|
mCoords[19] = lat1;
|
||||||
|
|
||||||
mIndex[1] = 10;
|
mIndex[2] = 8;
|
||||||
|
mIndex[3] = 2;
|
||||||
|
|
||||||
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, mIndex, true);
|
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, mIndex, true);
|
||||||
|
|
||||||
lon1 = (float) MercatorProjection.pixelXToLongitude(cx, tile.zoomLevel) * 1000000;
|
lon1 = Tile.TILE_SIZE / 2;
|
||||||
lat1 = (float) MercatorProjection.pixelXToLongitude(cx, tile.zoomLevel) * 1000000;
|
lat1 = Tile.TILE_SIZE / 2;
|
||||||
|
|
||||||
mNameTags = new Tag[2];
|
mNameTags = new Tag[2];
|
||||||
mNameTags[0] = new Tag("place", "city");
|
mNameTags[0] = new Tag("place", "city");
|
||||||
mNameTags[1] = new Tag("name", "check one check two, YO!");
|
mNameTags[1] = new Tag("name", tile.toString());
|
||||||
mapDatabaseCallback.renderPointOfInterest((byte) 0, (int) lat1, (int) lon1,
|
mapDatabaseCallback.renderPointOfInterest((byte) 0, mNameTags, (int) lat1,
|
||||||
mNameTags);
|
(int) lon1);
|
||||||
|
|
||||||
return QueryResult.SUCCESS;
|
return QueryResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMapProjection() {
|
public String getMapProjection() {
|
||||||
return PROJECTION;
|
return null; // PROJECTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -185,8 +136,6 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,143 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.stuff;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.DriverManager;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.oscim.core.MapPosition;
|
|
||||||
import org.oscim.view.MapView;
|
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Message;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class RegionLookup {
|
|
||||||
/* package */final static String TAG = RegionLookup.class.getName();
|
|
||||||
|
|
||||||
private Connection connection = null;
|
|
||||||
private PreparedStatement prepQuery = null;
|
|
||||||
|
|
||||||
private MapView mMapView;
|
|
||||||
|
|
||||||
private final Handler mHandler = new Handler() {
|
|
||||||
@Override
|
|
||||||
public void handleMessage(Message msg) {
|
|
||||||
Log.d(TAG, "message: " + msg.what);
|
|
||||||
// switch (msg.what) {
|
|
||||||
// handle update
|
|
||||||
// .....
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final String QUERY = "" +
|
|
||||||
"SELECT * from __get_regions_around(?,?)";
|
|
||||||
|
|
||||||
public RegionLookup(MapView mapView) {
|
|
||||||
mMapView = mapView;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean connect() {
|
|
||||||
Connection conn = null;
|
|
||||||
String dburl = "jdbc:postgresql://city.informatik.uni-bremen.de:5432/gis";
|
|
||||||
|
|
||||||
Properties dbOpts = new Properties();
|
|
||||||
dbOpts.setProperty("user", "osm");
|
|
||||||
dbOpts.setProperty("password", "osm");
|
|
||||||
dbOpts.setProperty("socketTimeout", "50");
|
|
||||||
dbOpts.setProperty("tcpKeepAlive", "true");
|
|
||||||
|
|
||||||
try {
|
|
||||||
DriverManager.setLoginTimeout(20);
|
|
||||||
Log.d(TAG, "Creating JDBC connection...");
|
|
||||||
|
|
||||||
Class.forName("org.postgresql.Driver");
|
|
||||||
conn = DriverManager.getConnection(dburl, dbOpts);
|
|
||||||
connection = conn;
|
|
||||||
prepQuery = conn.prepareStatement(QUERY);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d(TAG, "Aborted due to error:" + e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean updatePosition() {
|
|
||||||
if (connection == null) {
|
|
||||||
if (!connect())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultSet r;
|
|
||||||
MapPosition pos = mMapView.getMapPosition().getMapPosition();
|
|
||||||
|
|
||||||
try {
|
|
||||||
prepQuery.setDouble(1, pos.lat);
|
|
||||||
prepQuery.setDouble(2, pos.lon);
|
|
||||||
|
|
||||||
Log.d(TAG, "" + prepQuery.toString());
|
|
||||||
prepQuery.execute();
|
|
||||||
r = prepQuery.getResultSet();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
connection = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
String level, name, boundary;
|
|
||||||
double minx, miny, maxx, maxy;
|
|
||||||
try {
|
|
||||||
while (r != null && r.next()) {
|
|
||||||
level = r.getString(1);
|
|
||||||
boundary = r.getString(2);
|
|
||||||
name = r.getString(3);
|
|
||||||
minx = r.getDouble(4);
|
|
||||||
miny = r.getDouble(5);
|
|
||||||
maxx = r.getDouble(6);
|
|
||||||
maxy = r.getDouble(7);
|
|
||||||
|
|
||||||
Log.d(TAG, "got:" + level + " b:" + boundary + " n:" + name + " " + minx
|
|
||||||
+ " " + miny + " " + maxx + " " + maxy);
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (SQLException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
connection = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateRegion() {
|
|
||||||
new AsyncTask<Object, Integer, Long>() {
|
|
||||||
@Override
|
|
||||||
protected Long doInBackground(Object... params) {
|
|
||||||
RegionLookup.this.updatePosition();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// protected void onPostExecute(Long result) {
|
|
||||||
// Log.d(TAG, "got sth " + result);
|
|
||||||
// }
|
|
||||||
}.execute(null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -17,9 +17,9 @@ package org.oscim.theme;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.oscim.core.LRUCache;
|
|
||||||
import org.oscim.core.Tag;
|
import org.oscim.core.Tag;
|
||||||
import org.oscim.theme.renderinstruction.RenderInstruction;
|
import org.oscim.theme.renderinstruction.RenderInstruction;
|
||||||
|
import org.oscim.utils.LRUCache;
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<style-pathtext name="road" k="name" font-size="16" fill="#101010" stroke="#ffffff" stroke-width="2.0" />
|
<style-pathtext name="road" k="name" font-size="16" fill="#101010" stroke="#ffffff" stroke-width="2.0" />
|
||||||
<style-pathtext name="major-road" k="name" font-style="bold" font-size="16" fill="#101010" stroke="#ffffff" stroke-width="2.0" />
|
<style-pathtext name="major-road" k="name" font-style="bold" font-size="16" fill="#101010" stroke="#ffffff" stroke-width="2.0" />
|
||||||
|
|
||||||
<style-area name="residential" fill="#f0f0ec" fade="10"/>
|
<style-area name="residential" fill="#f0eee8" fade="10"/>
|
||||||
|
|
||||||
<style-area name="railway|industrial" fill="#f2eeef" fade="10"/>
|
<style-area name="railway|industrial" fill="#f2eeef" fade="10"/>
|
||||||
<!-- "#f0fae7" mint green -->
|
<!-- "#f0fae7" mint green -->
|
||||||
@ -66,7 +66,7 @@
|
|||||||
|
|
||||||
<style-line name="water:outline" stroke="#a4bbcc" width="1.0" fixed="true" cap="butt" />
|
<style-line name="water:outline" stroke="#a4bbcc" width="1.0" fixed="true" cap="butt" />
|
||||||
<style-line name="water" stroke="#b4cbdc" width="1.0" cap="butt" />
|
<style-line name="water" stroke="#b4cbdc" width="1.0" cap="butt" />
|
||||||
<style-area name="water" fill="#b4cbdc" />
|
<style-area name="water" fill="#a3c9f3" />
|
||||||
<!-- no-go area boundary -->
|
<!-- no-go area boundary -->
|
||||||
<style-line name="fence" stroke="#444444" width="1.2" fixed="true" cap="butt"/>
|
<style-line name="fence" stroke="#444444" width="1.2" fixed="true" cap="butt"/>
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.utils;
|
package org.oscim.utils;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
1808
src/org/oscim/utils/GLSurfaceView.java
Normal file
1808
src/org/oscim/utils/GLSurfaceView.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.utils;
|
package org.oscim.utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
@ -1,4 +1,4 @@
|
|||||||
package org.oscim.view.utils;
|
package org.oscim.utils;
|
||||||
|
|
||||||
import javax.microedition.khronos.egl.EGL10;
|
import javax.microedition.khronos.egl.EGL10;
|
||||||
import javax.microedition.khronos.egl.EGLConfig;
|
import javax.microedition.khronos.egl.EGLConfig;
|
@ -12,8 +12,9 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.utils;
|
package org.oscim.utils;
|
||||||
|
|
||||||
|
import static android.opengl.GLES20.glUniform4f;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
import android.opengl.GLUtils;
|
import android.opengl.GLUtils;
|
||||||
@ -142,4 +143,20 @@ public class GlUtils {
|
|||||||
}
|
}
|
||||||
return oom;
|
return oom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setBlendColors(int handle, float[] c1, float[] c2, float alpha) {
|
||||||
|
|
||||||
|
glUniform4f(handle,
|
||||||
|
c1[0] * (1 - alpha) + c2[0] * alpha,
|
||||||
|
c1[1] * (1 - alpha) + c2[1] * alpha,
|
||||||
|
c1[2] * (1 - alpha) + c2[2] * alpha, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setColor(int handle, float[] c, float alpha) {
|
||||||
|
if (alpha >= 1)
|
||||||
|
GLES20.glUniform4fv(handle, 1, c, 0);
|
||||||
|
else
|
||||||
|
glUniform4f(handle, c[0] * alpha, c[1] * alpha, c[2] * alpha, alpha);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.core;
|
package org.oscim.utils;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.mapgenerator;
|
package org.oscim.utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract base class for threads which support pausing and resuming.
|
* An abstract base class for threads which support pausing and resuming.
|
@ -30,7 +30,7 @@ public class Compass {
|
|||||||
|
|
||||||
if (mMapView != null) {
|
if (mMapView != null) {
|
||||||
mMapView.getMapPosition().setRotation(mAngle);
|
mMapView.getMapPosition().setRotation(mAngle);
|
||||||
mMapView.redrawTiles();
|
mMapView.redrawMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ public class Compass {
|
|||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
mSensorManager.registerListener(mListener, mSensor,
|
mSensorManager.registerListener(mListener, mSensor,
|
||||||
SensorManager.SENSOR_DELAY_GAME);
|
SensorManager.SENSOR_DELAY_UI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void disable() {
|
void disable() {
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.oscim.view;
|
|
||||||
|
|
||||||
import org.oscim.theme.RenderTheme;
|
|
||||||
import org.oscim.view.mapgenerator.IMapGenerator;
|
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
|
||||||
|
|
||||||
import android.opengl.GLSurfaceView;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public interface IMapRenderer extends GLSurfaceView.Renderer {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param tile
|
|
||||||
* Tile data ready for rendering
|
|
||||||
* @return true
|
|
||||||
*/
|
|
||||||
public boolean passTile(JobTile tile);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* called by MapView on position and map changes
|
|
||||||
*
|
|
||||||
* @param clear
|
|
||||||
* recreate all tiles (i.e. on theme change)
|
|
||||||
*/
|
|
||||||
public void updateMap(boolean clear);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return new MapGenerator Instance for this Renderer
|
|
||||||
*/
|
|
||||||
public IMapGenerator createMapGenerator();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param t
|
|
||||||
* the theme
|
|
||||||
*/
|
|
||||||
public void setRenderTheme(RenderTheme t);
|
|
||||||
|
|
||||||
}
|
|
@ -37,7 +37,7 @@ import android.content.SharedPreferences.Editor;
|
|||||||
public abstract class MapActivity extends Activity {
|
public abstract class MapActivity extends Activity {
|
||||||
private static final String KEY_LATITUDE = "latitude";
|
private static final String KEY_LATITUDE = "latitude";
|
||||||
private static final String KEY_LONGITUDE = "longitude";
|
private static final String KEY_LONGITUDE = "longitude";
|
||||||
private static final String KEY_MAP_FILE = "mapFile";
|
// private static final String KEY_MAP_FILE = "mapFile";
|
||||||
private static final String KEY_ZOOM_LEVEL = "zoomLevel";
|
private static final String KEY_ZOOM_LEVEL = "zoomLevel";
|
||||||
private static final String PREFERENCES_FILE = "MapActivity";
|
private static final String PREFERENCES_FILE = "MapActivity";
|
||||||
private static final String KEY_THEME = "Theme";
|
private static final String KEY_THEME = "Theme";
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view;
|
|
||||||
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A factory for the internal MapRenderer implementations.
|
|
||||||
*/
|
|
||||||
public final class MapRendererFactory {
|
|
||||||
private static final String MAP_RENDERER_ATTRIBUTE_NAME = "mapRenderer";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mapView
|
|
||||||
* ...
|
|
||||||
* @param attributeSet
|
|
||||||
* A collection of attributes which includes the desired MapRenderer.
|
|
||||||
* @return a new MapRenderer instance.
|
|
||||||
*/
|
|
||||||
public static IMapRenderer createMapRenderer(MapView mapView,
|
|
||||||
AttributeSet attributeSet) {
|
|
||||||
String mapRendererName = attributeSet.getAttributeValue(null,
|
|
||||||
MAP_RENDERER_ATTRIBUTE_NAME);
|
|
||||||
if (mapRendererName == null) {
|
|
||||||
return new org.oscim.view.glrenderer.MapRenderer(mapView);
|
|
||||||
}
|
|
||||||
|
|
||||||
MapRenderers mapRendererInternal = MapRenderers.valueOf(mapRendererName);
|
|
||||||
return MapRendererFactory.createMapRenderer(mapView, mapRendererInternal);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MapRenderers getMapRenderer(AttributeSet attributeSet) {
|
|
||||||
String mapRendererName = attributeSet.getAttributeValue(null,
|
|
||||||
MAP_RENDERER_ATTRIBUTE_NAME);
|
|
||||||
if (mapRendererName == null) {
|
|
||||||
return MapRenderers.GL_RENDERER;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MapRenderers.valueOf(mapRendererName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mapView
|
|
||||||
* ...
|
|
||||||
* @param mapRendererInternal
|
|
||||||
* the internal MapRenderer implementation.
|
|
||||||
* @return a new MapRenderer instance.
|
|
||||||
*/
|
|
||||||
public static IMapRenderer createMapRenderer(MapView mapView,
|
|
||||||
MapRenderers mapRendererInternal) {
|
|
||||||
switch (mapRendererInternal) {
|
|
||||||
case SW_RENDERER:
|
|
||||||
return new org.oscim.view.swrenderer.MapRenderer(mapView);
|
|
||||||
case GL_RENDERER:
|
|
||||||
return new org.oscim.view.glrenderer.MapRenderer(mapView);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("unknown enum value: " + mapRendererInternal);
|
|
||||||
}
|
|
||||||
|
|
||||||
private MapRendererFactory() {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
}
|
|
@ -30,30 +30,29 @@ import org.oscim.database.MapDatabaseFactory;
|
|||||||
import org.oscim.database.MapDatabases;
|
import org.oscim.database.MapDatabases;
|
||||||
import org.oscim.database.MapInfo;
|
import org.oscim.database.MapInfo;
|
||||||
import org.oscim.database.OpenResult;
|
import org.oscim.database.OpenResult;
|
||||||
import org.oscim.stuff.RegionLookup;
|
|
||||||
import org.oscim.theme.ExternalRenderTheme;
|
import org.oscim.theme.ExternalRenderTheme;
|
||||||
import org.oscim.theme.InternalRenderTheme;
|
import org.oscim.theme.InternalRenderTheme;
|
||||||
import org.oscim.theme.RenderTheme;
|
import org.oscim.theme.RenderTheme;
|
||||||
import org.oscim.theme.RenderThemeHandler;
|
import org.oscim.theme.RenderThemeHandler;
|
||||||
import org.oscim.theme.Theme;
|
import org.oscim.theme.Theme;
|
||||||
import org.oscim.view.mapgenerator.IMapGenerator;
|
import org.oscim.view.generator.JobQueue;
|
||||||
import org.oscim.view.mapgenerator.JobQueue;
|
import org.oscim.view.generator.JobTile;
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
import org.oscim.view.generator.MapWorker;
|
||||||
import org.oscim.view.mapgenerator.MapWorker;
|
import org.oscim.view.renderer.MapGenerator;
|
||||||
import org.oscim.view.utils.GlConfigChooser;
|
import org.oscim.view.renderer.MapRenderer;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.opengl.GLSurfaceView;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A MapView shows a map on the display of the device. It handles all user input and touch gestures to move and zoom the
|
* A MapView shows a map on the display of the device. It handles all user input and touch gestures to move and zoom the
|
||||||
* map.
|
* map.
|
||||||
*/
|
*/
|
||||||
public class MapView extends GLSurfaceView {
|
public class MapView extends FrameLayout {
|
||||||
|
|
||||||
final static String TAG = "MapView";
|
final static String TAG = "MapView";
|
||||||
|
|
||||||
@ -67,19 +66,23 @@ public class MapView extends GLSurfaceView {
|
|||||||
|
|
||||||
public final static boolean debugFrameTime = false;
|
public final static boolean debugFrameTime = false;
|
||||||
|
|
||||||
|
public final static boolean testRegionZoom = false;
|
||||||
|
RegionLookup mRegionLookup;
|
||||||
|
|
||||||
public boolean enableRotation = false;
|
public boolean enableRotation = false;
|
||||||
public boolean enableCompass = false;
|
public boolean enableCompass = false;
|
||||||
|
|
||||||
private final MapViewPosition mMapViewPosition;
|
private final MapViewPosition mMapViewPosition;
|
||||||
|
|
||||||
private final MapZoomControls mMapZoomControls;
|
private final MapZoomControls mMapZoomControls;
|
||||||
private final Projection mProjection;
|
|
||||||
private final TouchHandler mTouchEventHandler;
|
private final TouchHandler mTouchEventHandler;
|
||||||
private final Compass mCompass;
|
private final Compass mCompass;
|
||||||
|
|
||||||
private IMapDatabase mMapDatabase;
|
private IMapDatabase mMapDatabase;
|
||||||
private MapDatabases mMapDatabaseType;
|
private MapDatabases mMapDatabaseType;
|
||||||
private IMapRenderer mMapRenderer;
|
|
||||||
|
private MapRenderer mMapRenderer;
|
||||||
private JobQueue mJobQueue;
|
private JobQueue mJobQueue;
|
||||||
private MapWorker mMapWorkers[];
|
private MapWorker mMapWorkers[];
|
||||||
private int mNumMapWorkers = 4;
|
private int mNumMapWorkers = 4;
|
||||||
@ -94,7 +97,7 @@ public class MapView extends GLSurfaceView {
|
|||||||
* if the context object is not an instance of {@link MapActivity} .
|
* if the context object is not an instance of {@link MapActivity} .
|
||||||
*/
|
*/
|
||||||
public MapView(Context context) {
|
public MapView(Context context) {
|
||||||
this(context, null, MapRenderers.GL_RENDERER, MapDatabases.MAP_READER);
|
this(context, null, MapDatabases.MAP_READER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,15 +109,13 @@ public class MapView extends GLSurfaceView {
|
|||||||
* if the context object is not an instance of {@link MapActivity} .
|
* if the context object is not an instance of {@link MapActivity} .
|
||||||
*/
|
*/
|
||||||
public MapView(Context context, AttributeSet attributeSet) {
|
public MapView(Context context, AttributeSet attributeSet) {
|
||||||
this(context, attributeSet,
|
this(context, attributeSet, MapDatabaseFactory.getMapDatabase(attributeSet));
|
||||||
MapRendererFactory.getMapRenderer(attributeSet),
|
|
||||||
MapDatabaseFactory.getMapDatabase(attributeSet));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean mDebugDatabase = false;
|
private boolean mDebugDatabase = false;
|
||||||
|
|
||||||
private MapView(Context context, AttributeSet attributeSet,
|
private MapView(Context context, AttributeSet attributeSet,
|
||||||
MapRenderers mapGeneratorType, MapDatabases mapDatabaseType) {
|
MapDatabases mapDatabaseType) {
|
||||||
|
|
||||||
super(context, attributeSet);
|
super(context, attributeSet);
|
||||||
|
|
||||||
@ -136,17 +137,13 @@ public class MapView extends GLSurfaceView {
|
|||||||
|
|
||||||
mMapViewPosition = new MapViewPosition(this);
|
mMapViewPosition = new MapViewPosition(this);
|
||||||
|
|
||||||
mMapZoomControls = new MapZoomControls(mapActivity, this);
|
|
||||||
|
|
||||||
mProjection = new MapViewProjection(this);
|
|
||||||
|
|
||||||
mTouchEventHandler = new TouchHandler(mapActivity, this);
|
mTouchEventHandler = new TouchHandler(mapActivity, this);
|
||||||
|
|
||||||
mCompass = new Compass(mapActivity, this);
|
mCompass = new Compass(mapActivity, this);
|
||||||
|
|
||||||
mJobQueue = new JobQueue();
|
mJobQueue = new JobQueue();
|
||||||
|
|
||||||
mMapRenderer = MapRendererFactory.createMapRenderer(this, mapGeneratorType);
|
mMapRenderer = new MapRenderer(context, this);
|
||||||
|
|
||||||
mMapWorkers = new MapWorker[mNumMapWorkers];
|
mMapWorkers = new MapWorker[mNumMapWorkers];
|
||||||
|
|
||||||
@ -159,7 +156,7 @@ public class MapView extends GLSurfaceView {
|
|||||||
mapDatabase = MapDatabaseFactory.createMapDatabase(mapDatabaseType);
|
mapDatabase = MapDatabaseFactory.createMapDatabase(mapDatabaseType);
|
||||||
}
|
}
|
||||||
|
|
||||||
IMapGenerator mapGenerator = mMapRenderer.createMapGenerator();
|
MapGenerator mapGenerator = new MapGenerator(this);
|
||||||
mapGenerator.setMapDatabase(mapDatabase);
|
mapGenerator.setMapDatabase(mapDatabase);
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
@ -180,22 +177,19 @@ public class MapView extends GLSurfaceView {
|
|||||||
setMapCenter(getStartPosition());
|
setMapCenter(getStartPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
setEGLConfigChooser(new GlConfigChooser());
|
LayoutParams params = new LayoutParams(
|
||||||
setEGLContextClientVersion(2);
|
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
android.view.ViewGroup.LayoutParams.MATCH_PARENT);
|
||||||
|
|
||||||
// setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
|
addView(mMapRenderer, params);
|
||||||
|
|
||||||
setRenderer(mMapRenderer);
|
if (testRegionZoom)
|
||||||
|
mRegionLookup = new RegionLookup(this);
|
||||||
if (!debugFrameTime)
|
|
||||||
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
|
|
||||||
|
|
||||||
mRegionLookup = new RegionLookup(this);
|
|
||||||
|
|
||||||
|
mMapZoomControls = new MapZoomControls(mapActivity, this);
|
||||||
|
mMapZoomControls.setShowMapZoomControls(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegionLookup mRegionLookup;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the map database which is used for reading map files.
|
* @return the map database which is used for reading map files.
|
||||||
*/
|
*/
|
||||||
@ -212,6 +206,9 @@ public class MapView extends GLSurfaceView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent motionEvent) {
|
public boolean onTouchEvent(MotionEvent motionEvent) {
|
||||||
|
// mMapZoomControls.onMapViewTouchEvent(motionEvent.getAction()
|
||||||
|
// & MotionEvent.ACTION_MASK);
|
||||||
|
|
||||||
if (this.isClickable())
|
if (this.isClickable())
|
||||||
return mTouchEventHandler.handleMotionEvent(motionEvent);
|
return mTouchEventHandler.handleMotionEvent(motionEvent);
|
||||||
|
|
||||||
@ -221,17 +218,21 @@ public class MapView extends GLSurfaceView {
|
|||||||
/**
|
/**
|
||||||
* Calculates all necessary tiles and adds jobs accordingly.
|
* Calculates all necessary tiles and adds jobs accordingly.
|
||||||
*/
|
*/
|
||||||
public void redrawTiles() {
|
public void redrawMap() {
|
||||||
mMapRenderer.updateMap(false);
|
mMapRenderer.updateMap(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clearAndRedrawMap() {
|
||||||
|
mMapRenderer.updateMap(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param debugSettings
|
* @param debugSettings
|
||||||
* the new DebugSettings for this MapView.
|
* the new DebugSettings for this MapView.
|
||||||
*/
|
*/
|
||||||
public void setDebugSettings(DebugSettings debugSettings) {
|
public void setDebugSettings(DebugSettings debugSettings) {
|
||||||
this.debugSettings = debugSettings;
|
this.debugSettings = debugSettings;
|
||||||
mMapRenderer.updateMap(true);
|
clearAndRedrawMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -262,7 +263,7 @@ public class MapView extends GLSurfaceView {
|
|||||||
|
|
||||||
for (MapWorker mapWorker : mMapWorkers) {
|
for (MapWorker mapWorker : mMapWorkers) {
|
||||||
|
|
||||||
IMapGenerator mapGenerator = mapWorker.getMapGenerator();
|
MapGenerator mapGenerator = mapWorker.getMapGenerator();
|
||||||
IMapDatabase mapDatabase = mapGenerator.getMapDatabase();
|
IMapDatabase mapDatabase = mapGenerator.getMapDatabase();
|
||||||
|
|
||||||
mapDatabase.close();
|
mapDatabase.close();
|
||||||
@ -276,7 +277,8 @@ public class MapView extends GLSurfaceView {
|
|||||||
|
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
mMapOptions = mapOptions;
|
mMapOptions = mapOptions;
|
||||||
mMapRenderer.updateMap(true);
|
clearAndRedrawMap();
|
||||||
|
|
||||||
Log.i(TAG, "MapDatabase ready");
|
Log.i(TAG, "MapDatabase ready");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -320,7 +322,7 @@ public class MapView extends GLSurfaceView {
|
|||||||
if (mDebugDatabase)
|
if (mDebugDatabase)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IMapGenerator mapGenerator;
|
MapGenerator mapGenerator;
|
||||||
|
|
||||||
Log.i(TAG, "setMapDatabase " + mapDatabaseType.name());
|
Log.i(TAG, "setMapDatabase " + mapDatabaseType.name());
|
||||||
|
|
||||||
@ -340,8 +342,6 @@ public class MapView extends GLSurfaceView {
|
|||||||
|
|
||||||
mJobQueue.clear();
|
mJobQueue.clear();
|
||||||
|
|
||||||
// String mapFile = mMapFile;
|
|
||||||
// mMapFile = null;
|
|
||||||
setMapOptions(null);
|
setMapOptions(null);
|
||||||
|
|
||||||
mapWorkersProceed();
|
mapWorkersProceed();
|
||||||
@ -369,7 +369,7 @@ public class MapView extends GLSurfaceView {
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
mRenderTheme = internalRenderTheme.name();
|
mRenderTheme = internalRenderTheme.name();
|
||||||
}
|
}
|
||||||
mMapRenderer.updateMap(true);
|
clearAndRedrawMap();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,7 +392,7 @@ public class MapView extends GLSurfaceView {
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
mRenderTheme = renderThemePath;
|
mRenderTheme = renderThemePath;
|
||||||
}
|
}
|
||||||
mMapRenderer.updateMap(true);
|
clearAndRedrawMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean setRenderTheme(Theme theme) {
|
private boolean setRenderTheme(Theme theme) {
|
||||||
@ -432,12 +432,18 @@ public class MapView extends GLSurfaceView {
|
|||||||
|
|
||||||
mJobQueue.clear();
|
mJobQueue.clear();
|
||||||
mapWorkersPause(true);
|
mapWorkersPause(true);
|
||||||
|
Log.d(TAG, "onSizeChanged" + width + " " + height);
|
||||||
super.onSizeChanged(width, height, oldWidth, oldHeight);
|
super.onSizeChanged(width, height, oldWidth, oldHeight);
|
||||||
|
|
||||||
mapWorkersProceed();
|
mapWorkersProceed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
|
super.onLayout(changed, left, top, right, bottom);
|
||||||
|
mMapZoomControls.onLayout(changed, left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
void destroy() {
|
void destroy() {
|
||||||
for (MapWorker mapWorker : mMapWorkers) {
|
for (MapWorker mapWorker : mMapWorkers) {
|
||||||
mapWorker.pause();
|
mapWorker.pause();
|
||||||
@ -454,59 +460,26 @@ public class MapView extends GLSurfaceView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void onPause() {
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
mapWorkersPause(false);
|
mapWorkersPause(false);
|
||||||
|
|
||||||
if (this.enableCompass)
|
if (this.enableCompass)
|
||||||
mCompass.disable();
|
mCompass.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void onResume() {
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
mapWorkersProceed();
|
mapWorkersProceed();
|
||||||
|
|
||||||
if (this.enableCompass)
|
if (this.enableCompass)
|
||||||
mCompass.enable();
|
mCompass.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Zooms in or out by the given amount of zoom levels.
|
|
||||||
*
|
|
||||||
* @param zoomLevelDiff
|
|
||||||
* the difference to the current zoom level.
|
|
||||||
* @return true if the zoom level was changed, false otherwise.
|
|
||||||
*/
|
|
||||||
public boolean zoom(byte zoomLevelDiff) {
|
|
||||||
|
|
||||||
int z = mMapViewPosition.getZoomLevel() + zoomLevelDiff;
|
|
||||||
if (zoomLevelDiff > 0) {
|
|
||||||
// check if zoom in is possible
|
|
||||||
if (z > getMaximumPossibleZoomLevel()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (zoomLevelDiff < 0) {
|
|
||||||
// check if zoom out is possible
|
|
||||||
if (z < mMapZoomControls.getZoomLevelMin()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mMapViewPosition.setZoomLevel((byte) z);
|
|
||||||
redrawTiles();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the maximum possible zoom level.
|
* @return the maximum possible zoom level.
|
||||||
*/
|
*/
|
||||||
byte getMaximumPossibleZoomLevel() {
|
byte getMaximumPossibleZoomLevel() {
|
||||||
return (byte) 20;
|
return (byte) MapViewPosition.MAX_ZOOMLEVEL;
|
||||||
// FIXME Math.min(mMapZoomControls.getZoomLevelMax(),
|
// Math.min(mMapZoomControls.getZoomLevelMax(),
|
||||||
// mMapGenerator.getZoomLevelMax());
|
// mMapGenerator.getZoomLevelMax());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,6 +502,9 @@ public class MapView extends GLSurfaceView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte limitZoomLevel(byte zoom) {
|
byte limitZoomLevel(byte zoom) {
|
||||||
|
if (mMapZoomControls == null)
|
||||||
|
return zoom;
|
||||||
|
|
||||||
return (byte) Math.max(Math.min(zoom, getMaximumPossibleZoomLevel()),
|
return (byte) Math.max(Math.min(zoom, getMaximumPossibleZoomLevel()),
|
||||||
mMapZoomControls.getZoomLevelMin());
|
mMapZoomControls.getZoomLevelMin());
|
||||||
}
|
}
|
||||||
@ -544,7 +520,7 @@ public class MapView extends GLSurfaceView {
|
|||||||
+ " lat: " + mapPosition.lat
|
+ " lat: " + mapPosition.lat
|
||||||
+ " lon: " + mapPosition.lon);
|
+ " lon: " + mapPosition.lon);
|
||||||
mMapViewPosition.setMapCenter(mapPosition);
|
mMapViewPosition.setMapCenter(mapPosition);
|
||||||
redrawTiles();
|
redrawMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,7 +19,6 @@ import org.oscim.core.MapPosition;
|
|||||||
import org.oscim.core.MercatorProjection;
|
import org.oscim.core.MercatorProjection;
|
||||||
|
|
||||||
import android.util.FloatMath;
|
import android.util.FloatMath;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A MapPosition stores the latitude and longitude coordinate of a MapView together with its zoom level.
|
* A MapPosition stores the latitude and longitude coordinate of a MapView together with its zoom level.
|
||||||
@ -27,7 +26,7 @@ import android.util.Log;
|
|||||||
public class MapViewPosition {
|
public class MapViewPosition {
|
||||||
private static float MAX_SCALE = 2.0f;
|
private static float MAX_SCALE = 2.0f;
|
||||||
private static float MIN_SCALE = 1.0f;
|
private static float MIN_SCALE = 1.0f;
|
||||||
private static int MAX_ZOOMLEVEL = 16;
|
public static int MAX_ZOOMLEVEL = 16;
|
||||||
|
|
||||||
private double mLatitude;
|
private double mLatitude;
|
||||||
private double mLongitude;
|
private double mLongitude;
|
||||||
@ -102,6 +101,43 @@ public class MapViewPosition {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get GeoPoint for a pixel on screen
|
||||||
|
*
|
||||||
|
* @param x
|
||||||
|
* ...
|
||||||
|
* @param y
|
||||||
|
* ...
|
||||||
|
* @return the GeoPoint
|
||||||
|
*/
|
||||||
|
public GeoPoint getOffsetPoint(float x, float y) {
|
||||||
|
double pixelX = MercatorProjection.longitudeToPixelX(mLongitude, mZoomLevel);
|
||||||
|
double pixelY = MercatorProjection.latitudeToPixelY(mLatitude, mZoomLevel);
|
||||||
|
|
||||||
|
double dx = ((mMapView.getWidth() >> 1) - x) / mScale;
|
||||||
|
double dy = ((mMapView.getHeight() >> 1) - y) / mScale;
|
||||||
|
|
||||||
|
if (mMapView.enableRotation || mMapView.enableCompass) {
|
||||||
|
double rad = Math.toRadians(mRotation);
|
||||||
|
double xx = dx * Math.cos(rad) + dy * -Math.sin(rad);
|
||||||
|
double yy = dx * Math.sin(rad) + dy * Math.cos(rad);
|
||||||
|
|
||||||
|
dx = pixelX - xx;
|
||||||
|
dy = pixelY - yy;
|
||||||
|
} else {
|
||||||
|
dx = pixelX - dx;
|
||||||
|
dy = pixelY - dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
double latitude = MercatorProjection.pixelYToLatitude(dy, mZoomLevel);
|
||||||
|
latitude = MercatorProjection.limitLatitude(latitude);
|
||||||
|
|
||||||
|
double longitude = MercatorProjection.pixelXToLongitude(dx, mZoomLevel);
|
||||||
|
longitude = MercatorProjection.limitLongitude(longitude);
|
||||||
|
|
||||||
|
return new GeoPoint(latitude, longitude);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves this MapViewPosition by the given amount of pixels.
|
* Moves this MapViewPosition by the given amount of pixels.
|
||||||
*
|
*
|
||||||
@ -113,22 +149,21 @@ public class MapViewPosition {
|
|||||||
public synchronized void moveMap(float mx, float my) {
|
public synchronized void moveMap(float mx, float my) {
|
||||||
double pixelX = MercatorProjection.longitudeToPixelX(mLongitude, mZoomLevel);
|
double pixelX = MercatorProjection.longitudeToPixelX(mLongitude, mZoomLevel);
|
||||||
double pixelY = MercatorProjection.latitudeToPixelY(mLatitude, mZoomLevel);
|
double pixelY = MercatorProjection.latitudeToPixelY(mLatitude, mZoomLevel);
|
||||||
double dx, dy;
|
|
||||||
|
double dx = mx / mScale;
|
||||||
|
double dy = my / mScale;
|
||||||
|
|
||||||
if (mMapView.enableRotation || mMapView.enableCompass) {
|
if (mMapView.enableRotation || mMapView.enableCompass) {
|
||||||
float rad = (float) Math.toRadians(mRotation);
|
double rad = Math.toRadians(mRotation);
|
||||||
dx = mx / mScale;
|
double x = dx * Math.cos(rad) + dy * -Math.sin(rad);
|
||||||
dy = my / mScale;
|
double y = dx * Math.sin(rad) + dy * Math.cos(rad);
|
||||||
|
|
||||||
double x = dx * FloatMath.cos(rad) + dy * -FloatMath.sin(rad);
|
|
||||||
double y = dx * FloatMath.sin(rad) + dy * FloatMath.cos(rad);
|
|
||||||
|
|
||||||
dx = pixelX - x;
|
dx = pixelX - x;
|
||||||
dy = pixelY - y;
|
dy = pixelY - y;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dx = pixelX - mx / mScale;
|
dx = pixelX - dx;
|
||||||
dy = pixelY - my / mScale;
|
dy = pixelY - dy;
|
||||||
}
|
}
|
||||||
mLatitude = MercatorProjection.pixelYToLatitude(dy, mZoomLevel);
|
mLatitude = MercatorProjection.pixelYToLatitude(dy, mZoomLevel);
|
||||||
mLatitude = MercatorProjection.limitLatitude(mLatitude);
|
mLatitude = MercatorProjection.limitLatitude(mLatitude);
|
||||||
@ -141,7 +176,7 @@ public class MapViewPosition {
|
|||||||
|
|
||||||
public synchronized void rotateMap(float angle, float cx, float cy) {
|
public synchronized void rotateMap(float angle, float cx, float cy) {
|
||||||
moveMap(cx, cy);
|
moveMap(cx, cy);
|
||||||
Log.d("MapViewPosition", "rotate:" + angle + " " + (mRotation - angle));
|
// Log.d("MapViewPosition", "rotate:" + angle + " " + (mRotation - angle));
|
||||||
mRotation -= angle;
|
mRotation -= angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,6 +203,10 @@ public class MapViewPosition {
|
|||||||
mScale = scale;
|
mScale = scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// synchronized void zoomBoundingBox(GeoPoint p1, GeoPoint p2) {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param scale
|
* @param scale
|
||||||
* ...
|
* ...
|
||||||
|
@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view;
|
|
||||||
|
|
||||||
import org.oscim.core.GeoPoint;
|
|
||||||
import org.oscim.core.MapPosition;
|
|
||||||
import org.oscim.core.MercatorProjection;
|
|
||||||
|
|
||||||
import android.graphics.Point;
|
|
||||||
|
|
||||||
class MapViewProjection implements Projection {
|
|
||||||
private static final String INVALID_MAP_VIEW_DIMENSIONS = "invalid MapView dimensions";
|
|
||||||
|
|
||||||
private final MapView mMapView;
|
|
||||||
|
|
||||||
MapViewProjection(MapView mapView) {
|
|
||||||
mMapView = mapView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GeoPoint fromPixels(int x, int y) {
|
|
||||||
if (mMapView.getWidth() <= 0 || mMapView.getHeight() <= 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
|
|
||||||
|
|
||||||
// calculate the pixel coordinates of the top left corner
|
|
||||||
double pixelX = MercatorProjection.longitudeToPixelX(mapPosition);
|
|
||||||
double pixelY = MercatorProjection.latitudeToPixelY(mapPosition);
|
|
||||||
pixelX -= mMapView.getWidth() >> 1;
|
|
||||||
pixelY -= mMapView.getHeight() >> 1;
|
|
||||||
|
|
||||||
// convert the pixel coordinates to a GeoPoint and return it
|
|
||||||
return new GeoPoint(MercatorProjection.pixelYToLatitude(pixelY + y,
|
|
||||||
mapPosition.zoomLevel),
|
|
||||||
MercatorProjection.pixelXToLongitude(pixelX + x, mapPosition.zoomLevel));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLatitudeSpan() {
|
|
||||||
if (mMapView.getWidth() > 0 && mMapView.getWidth() > 0) {
|
|
||||||
GeoPoint top = fromPixels(0, 0);
|
|
||||||
GeoPoint bottom = fromPixels(0, mMapView.getHeight());
|
|
||||||
return Math.abs(top.latitudeE6 - bottom.latitudeE6);
|
|
||||||
}
|
|
||||||
throw new IllegalStateException(INVALID_MAP_VIEW_DIMENSIONS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLongitudeSpan() {
|
|
||||||
if (mMapView.getWidth() > 0 && mMapView.getWidth() > 0) {
|
|
||||||
GeoPoint left = fromPixels(0, 0);
|
|
||||||
GeoPoint right = fromPixels(mMapView.getWidth(), 0);
|
|
||||||
return Math.abs(left.longitudeE6 - right.longitudeE6);
|
|
||||||
}
|
|
||||||
throw new IllegalStateException(INVALID_MAP_VIEW_DIMENSIONS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float metersToPixels(float meters, byte zoom) {
|
|
||||||
double latitude = mMapView.getMapPosition().getMapCenter().getLatitude();
|
|
||||||
double groundResolution = MercatorProjection.calculateGroundResolution(latitude,
|
|
||||||
zoom);
|
|
||||||
return (float) (meters * (1 / groundResolution));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Point toPixels(GeoPoint in, Point out) {
|
|
||||||
if (mMapView.getWidth() <= 0 || mMapView.getHeight() <= 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
|
|
||||||
|
|
||||||
// calculate the pixel coordinates of the top left corner
|
|
||||||
double pixelX = MercatorProjection.longitudeToPixelX(mapPosition);
|
|
||||||
double pixelY = MercatorProjection.latitudeToPixelY(mapPosition);
|
|
||||||
pixelX -= mMapView.getWidth() >> 1;
|
|
||||||
pixelY -= mMapView.getHeight() >> 1;
|
|
||||||
|
|
||||||
if (out == null) {
|
|
||||||
// create a new point and return it
|
|
||||||
return new Point(
|
|
||||||
(int) (MercatorProjection.longitudeToPixelX(in.getLongitude(),
|
|
||||||
mapPosition.zoomLevel) - pixelX),
|
|
||||||
(int) (MercatorProjection.latitudeToPixelY(in.getLatitude(),
|
|
||||||
mapPosition.zoomLevel) - pixelY));
|
|
||||||
}
|
|
||||||
|
|
||||||
// reuse the existing point
|
|
||||||
out.x = (int) (MercatorProjection.longitudeToPixelX(in.getLongitude(),
|
|
||||||
mapPosition.zoomLevel) - pixelX);
|
|
||||||
out.y = (int) (MercatorProjection.latitudeToPixelY(in.getLatitude(),
|
|
||||||
mapPosition.zoomLevel) - pixelY);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Point toPoint(GeoPoint in, Point out, byte zoom) {
|
|
||||||
if (out == null) {
|
|
||||||
// create a new point and return it
|
|
||||||
return new Point((int) MercatorProjection.longitudeToPixelX(
|
|
||||||
in.getLongitude(), zoom),
|
|
||||||
(int) MercatorProjection.latitudeToPixelY(in.getLatitude(), zoom));
|
|
||||||
}
|
|
||||||
|
|
||||||
// reuse the existing point
|
|
||||||
out.x = (int) MercatorProjection.longitudeToPixelX(in.getLongitude(), zoom);
|
|
||||||
out.y = (int) MercatorProjection.latitudeToPixelY(in.getLatitude(), zoom);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.view;
|
package org.oscim.view;
|
||||||
|
|
||||||
import org.oscim.view.mapgenerator.IMapGenerator;
|
import org.oscim.view.renderer.MapGenerator;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@ -23,6 +23,7 @@ import android.view.Gravity;
|
|||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
|
import android.view.ViewGroup.LayoutParams;
|
||||||
import android.widget.ZoomControls;
|
import android.widget.ZoomControls;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,28 +45,35 @@ public class MapZoomControls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class ZoomInClickListener implements View.OnClickListener {
|
private static class ZoomInClickListener implements View.OnClickListener {
|
||||||
private final MapView mMapView;
|
private final MapZoomControls mMapZoomControls;
|
||||||
|
|
||||||
ZoomInClickListener(MapView mapView) {
|
ZoomInClickListener(MapZoomControls mapZoomControls) {
|
||||||
mMapView = mapView;
|
mMapZoomControls = mapZoomControls;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
mMapView.zoom((byte) 1);
|
// if (MapView.testRegionZoom)
|
||||||
|
// mMapView.mRegionLookup.updateRegion(1, null);
|
||||||
|
// else
|
||||||
|
// MapZoomControls.this.zoom((byte) 1);
|
||||||
|
mMapZoomControls.zoom((byte) 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ZoomOutClickListener implements View.OnClickListener {
|
private static class ZoomOutClickListener implements View.OnClickListener {
|
||||||
private final MapView mMapView;
|
private final MapZoomControls mMapZoomControls;
|
||||||
|
|
||||||
ZoomOutClickListener(MapView mapView) {
|
ZoomOutClickListener(MapZoomControls mapZoomControls) {
|
||||||
mMapView = mapView;
|
mMapZoomControls = mapZoomControls;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
mMapView.zoom((byte) -1);
|
// if (MapView.testRegionZoom)
|
||||||
|
// mMapView.mRegionLookup.updateRegion(-1, null);
|
||||||
|
// else
|
||||||
|
mMapZoomControls.zoom((byte) -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,12 +86,12 @@ public class MapZoomControls {
|
|||||||
/**
|
/**
|
||||||
* Default maximum zoom level.
|
* Default maximum zoom level.
|
||||||
*/
|
*/
|
||||||
private static final byte DEFAULT_ZOOM_LEVEL_MAX = 22;
|
private static final byte DEFAULT_ZOOM_LEVEL_MAX = 18;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default minimum zoom level.
|
* Default minimum zoom level.
|
||||||
*/
|
*/
|
||||||
private static final byte DEFAULT_ZOOM_LEVEL_MIN = 0;
|
private static final byte DEFAULT_ZOOM_LEVEL_MIN = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message code for the handler to hide the zoom controls.
|
* Message code for the handler to hide the zoom controls.
|
||||||
@ -108,22 +116,53 @@ public class MapZoomControls {
|
|||||||
private final Handler mZoomControlsHideHandler;
|
private final Handler mZoomControlsHideHandler;
|
||||||
private byte mZoomLevelMax;
|
private byte mZoomLevelMax;
|
||||||
private byte mZoomLevelMin;
|
private byte mZoomLevelMin;
|
||||||
|
private MapView mMapView;
|
||||||
|
|
||||||
MapZoomControls(Context context, final MapView mapView) {
|
MapZoomControls(Context context, final MapView mapView) {
|
||||||
mZoomControls = new ZoomControls(context);
|
mZoomControls = new ZoomControls(context);
|
||||||
mShowMapZoomControls = true;
|
mShowMapZoomControls = true;
|
||||||
mZoomLevelMax = DEFAULT_ZOOM_LEVEL_MAX;
|
mZoomLevelMax = DEFAULT_ZOOM_LEVEL_MAX;
|
||||||
mZoomLevelMin = DEFAULT_ZOOM_LEVEL_MIN;
|
mZoomLevelMin = DEFAULT_ZOOM_LEVEL_MIN;
|
||||||
mZoomControls.setVisibility(View.GONE);
|
if (!MapView.testRegionZoom)
|
||||||
|
mZoomControls.setVisibility(View.GONE);
|
||||||
mZoomControlsGravity = DEFAULT_ZOOM_CONTROLS_GRAVITY;
|
mZoomControlsGravity = DEFAULT_ZOOM_CONTROLS_GRAVITY;
|
||||||
|
|
||||||
mZoomControls.setOnZoomInClickListener(new ZoomInClickListener(mapView));
|
mZoomControls.setOnZoomInClickListener(new ZoomInClickListener(this));
|
||||||
mZoomControls.setOnZoomOutClickListener(new ZoomOutClickListener(mapView));
|
mZoomControls.setOnZoomOutClickListener(new ZoomOutClickListener(this));
|
||||||
mZoomControlsHideHandler = new ZoomControlsHideHandler(mZoomControls);
|
mZoomControlsHideHandler = new ZoomControlsHideHandler(mZoomControls);
|
||||||
|
|
||||||
// int wrapContent = android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
int wrapContent = android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||||
// LayoutParams layoutParams = new LayoutParams(wrapContent, wrapContent);
|
LayoutParams layoutParams = new LayoutParams(wrapContent, wrapContent);
|
||||||
// mapView.addView(zoomControls, layoutParams);
|
mapView.addView(mZoomControls, layoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zooms in or out by the given amount of zoom levels.
|
||||||
|
*
|
||||||
|
* @param zoomLevelDiff
|
||||||
|
* the difference to the current zoom level.
|
||||||
|
* @return true if the zoom level was changed, false otherwise.
|
||||||
|
*/
|
||||||
|
boolean zoom(byte zoomLevelDiff) {
|
||||||
|
MapViewPosition mapViewPosition = mMapView.getMapViewPosition();
|
||||||
|
int z = mapViewPosition.getZoomLevel() + zoomLevelDiff;
|
||||||
|
if (zoomLevelDiff > 0) {
|
||||||
|
// check if zoom in is possible
|
||||||
|
if (z > mZoomLevelMax) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (zoomLevelDiff < 0) {
|
||||||
|
// check if zoom out is possible
|
||||||
|
if (z < getZoomLevelMin()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mapViewPosition.setZoomLevel((byte) z);
|
||||||
|
mMapView.redrawMap();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,11 +195,11 @@ public class MapZoomControls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param showMapZoomControls
|
* @param show
|
||||||
* true if the zoom controls should be visible, false otherwise.
|
* true if the zoom controls should be visible, false otherwise.
|
||||||
*/
|
*/
|
||||||
public void setShowMapZoomControls(boolean showMapZoomControls) {
|
public void setShowMapZoomControls(boolean show) {
|
||||||
mShowMapZoomControls = false;
|
mShowMapZoomControls = show;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -181,7 +220,7 @@ public class MapZoomControls {
|
|||||||
/**
|
/**
|
||||||
* Sets the maximum zoom level of the map.
|
* Sets the maximum zoom level of the map.
|
||||||
* <p>
|
* <p>
|
||||||
* The maximum possible zoom level of the MapView depends also on the current {@link IMapGenerator}. For example,
|
* The maximum possible zoom level of the MapView depends also on the current {@link MapGenerator}. For example,
|
||||||
* downloading map tiles may only be possible up to a certain zoom level. Setting a higher maximum zoom level has no
|
* downloading map tiles may only be possible up to a certain zoom level. Setting a higher maximum zoom level has no
|
||||||
* effect in this case.
|
* effect in this case.
|
||||||
*
|
*
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view;
|
|
||||||
|
|
||||||
import org.oscim.core.GeoPoint;
|
|
||||||
|
|
||||||
import android.graphics.Point;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Projection translates between the pixel coordinate system on the screen and geographical points on the earth. To
|
|
||||||
* retrieve the currently used Projection for a given MapView, call the {@link MapView#getProjection()} method.
|
|
||||||
*/
|
|
||||||
public interface Projection {
|
|
||||||
/**
|
|
||||||
* Translates the given screen coordinates to a {@link GeoPoint}. If the corresponding MapView has no valid
|
|
||||||
* dimensions (width and height > 0), null is returned.
|
|
||||||
*
|
|
||||||
* @param x
|
|
||||||
* the pixel x coordinate on the screen.
|
|
||||||
* @param y
|
|
||||||
* the pixel y coordinate on the screen.
|
|
||||||
* @return a new {@link GeoPoint} or null, if the corresponding MapView has no valid dimensions.
|
|
||||||
*/
|
|
||||||
GeoPoint fromPixels(int x, int y);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the latitude span from the top to the bottom of the map in microdegrees (degrees * 10^6).
|
|
||||||
* @throws IllegalStateException
|
|
||||||
* if the MapView dimensions are not valid (width and height > 0).
|
|
||||||
*/
|
|
||||||
int getLatitudeSpan();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the longitude span from the left to the right of the map in microdegrees (degrees * 10^6).
|
|
||||||
* @throws IllegalStateException
|
|
||||||
* if the MapView dimensions are not valid (width and height > 0).
|
|
||||||
*/
|
|
||||||
int getLongitudeSpan();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the given distance in meters at the given zoom level to the corresponding number of horizontal pixels.
|
|
||||||
* The calculation is carried out at the current latitude coordinate.
|
|
||||||
*
|
|
||||||
* @param meters
|
|
||||||
* the distance in meters.
|
|
||||||
* @param zoomLevel
|
|
||||||
* the zoom level at which the distance should be calculated.
|
|
||||||
* @return the number of pixels at the current map position and the given zoom level.
|
|
||||||
*/
|
|
||||||
float metersToPixels(float meters, byte zoomLevel);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates the given {@link GeoPoint} to relative pixel coordinates on the screen. If the corresponding MapView
|
|
||||||
* has no valid dimensions (width and height > 0), null is returned.
|
|
||||||
*
|
|
||||||
* @param in
|
|
||||||
* the geographical point to convert.
|
|
||||||
* @param out
|
|
||||||
* an already existing object to use for the output. If this parameter is null, a new Point object will
|
|
||||||
* be created and returned.
|
|
||||||
* @return a Point which is relative to the top-left of the MapView or null, if the corresponding MapView has no
|
|
||||||
* valid dimensions.
|
|
||||||
*/
|
|
||||||
Point toPixels(GeoPoint in, Point out);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates the given {@link GeoPoint} to absolute pixel coordinates on the world map.
|
|
||||||
*
|
|
||||||
* @param in
|
|
||||||
* the geographical point to convert.
|
|
||||||
* @param out
|
|
||||||
* an already existing object to use for the output. If this parameter is null, a new Point object will
|
|
||||||
* be created and returned.
|
|
||||||
* @param zoomLevel
|
|
||||||
* the zoom level at which the point should be converted.
|
|
||||||
* @return a Point which is relative to the top-left of the world map.
|
|
||||||
*/
|
|
||||||
Point toPoint(GeoPoint in, Point out, byte zoomLevel);
|
|
||||||
}
|
|
266
src/org/oscim/view/RegionLookup.java
Normal file
266
src/org/oscim/view/RegionLookup.java
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.oscim.view;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.oscim.core.GeoPoint;
|
||||||
|
import org.oscim.core.MapPosition;
|
||||||
|
import org.oscim.core.MercatorProjection;
|
||||||
|
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.util.FloatMath;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
public class RegionLookup {
|
||||||
|
final static String TAG = RegionLookup.class.getName();
|
||||||
|
|
||||||
|
class BBox {
|
||||||
|
String level, name, boundary;
|
||||||
|
GeoPoint min, max;
|
||||||
|
float area;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Connection connection = null;
|
||||||
|
private PreparedStatement prepQuery = null;
|
||||||
|
|
||||||
|
/* package */MapView mMapView;
|
||||||
|
/* pacakge */BBox mSelected;
|
||||||
|
|
||||||
|
// __get_regions_around(lat double precision, lon double precision)
|
||||||
|
// returns table (level text, boundary text, name text, xmin double precision, ymin double precision, xmax double
|
||||||
|
// precision, ymax double precision)
|
||||||
|
// language sql as
|
||||||
|
// $$
|
||||||
|
// select admin_level, boundary, name, xmin(box), ymin(box), xmax(box), ymax(box) from
|
||||||
|
// .. (select distinct on (box) * from
|
||||||
|
// .... (select *, st_transform(st_envelope(way),4326) box
|
||||||
|
// ...... from planet_polygon, st_transform(st_setsrid(st_makepoint($2,$1),4326),900913) point
|
||||||
|
// ...... where (boundary is not null) and st_contains(way, point)
|
||||||
|
// .... )p
|
||||||
|
// .. )p order by st_area(box)
|
||||||
|
// $$;
|
||||||
|
private static final String QUERY = "SELECT * from __get_regions_around(?,?)";
|
||||||
|
|
||||||
|
public RegionLookup(MapView mapView) {
|
||||||
|
mMapView = mapView;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean connect() {
|
||||||
|
Connection conn = null;
|
||||||
|
String dburl = "jdbc:postgresql://city.informatik.uni-bremen.de:5432/gis";
|
||||||
|
|
||||||
|
Properties dbOpts = new Properties();
|
||||||
|
dbOpts.setProperty("user", "osm");
|
||||||
|
dbOpts.setProperty("password", "osm");
|
||||||
|
dbOpts.setProperty("socketTimeout", "50");
|
||||||
|
dbOpts.setProperty("tcpKeepAlive", "true");
|
||||||
|
|
||||||
|
try {
|
||||||
|
DriverManager.setLoginTimeout(20);
|
||||||
|
Log.d(TAG, "Creating JDBC connection...");
|
||||||
|
|
||||||
|
Class.forName("org.postgresql.Driver");
|
||||||
|
conn = DriverManager.getConnection(dburl, dbOpts);
|
||||||
|
connection = conn;
|
||||||
|
prepQuery = conn.prepareStatement(QUERY);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.d(TAG, "Aborted due to error:" + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean updatePosition() {
|
||||||
|
if (connection == null) {
|
||||||
|
if (!connect())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultSet r;
|
||||||
|
|
||||||
|
MapPosition pos = mMapView.getMapPosition().getMapPosition();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (mPos == null) {
|
||||||
|
prepQuery.setDouble(1, pos.lat);
|
||||||
|
prepQuery.setDouble(2, pos.lon);
|
||||||
|
} else {
|
||||||
|
prepQuery.setDouble(1, mPos.getLatitude());
|
||||||
|
prepQuery.setDouble(2, mPos.getLongitude());
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, prepQuery.toString());
|
||||||
|
|
||||||
|
prepQuery.execute();
|
||||||
|
r = prepQuery.getResultSet();
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
connection = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<BBox> boxes = new ArrayList<BBox>(10);
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (r != null && r.next()) {
|
||||||
|
BBox bbox = new BBox();
|
||||||
|
|
||||||
|
bbox.level = r.getString(1);
|
||||||
|
bbox.boundary = r.getString(2);
|
||||||
|
bbox.name = r.getString(3);
|
||||||
|
bbox.min = new GeoPoint(r.getDouble(5), r.getDouble(4));
|
||||||
|
bbox.max = new GeoPoint(r.getDouble(7), r.getDouble(6));
|
||||||
|
|
||||||
|
bbox.area = (float) Math.abs((bbox.max.getLatitude()
|
||||||
|
- bbox.min.getLatitude())
|
||||||
|
* (bbox.max.getLongitude()
|
||||||
|
- bbox.min.getLongitude()));
|
||||||
|
Log.d(TAG, "got:" + bbox.area
|
||||||
|
+ " " + bbox.level + " b:" + bbox.boundary +
|
||||||
|
" n:" + bbox.name + " " + bbox.min + " " + bbox.max);
|
||||||
|
boxes.add(bbox);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
connection = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double w = (mMapView.getWidth() >> 1) / pos.scale;
|
||||||
|
double h = (mMapView.getHeight() >> 1) / pos.scale;
|
||||||
|
|
||||||
|
float minx = (float) MercatorProjection
|
||||||
|
.pixelXToLongitude(pos.x - w, pos.zoomLevel);
|
||||||
|
float maxx = (float) MercatorProjection
|
||||||
|
.pixelXToLongitude(pos.x + w, pos.zoomLevel);
|
||||||
|
float miny = (float) MercatorProjection
|
||||||
|
.pixelYToLatitude(pos.y - h, pos.zoomLevel);
|
||||||
|
float maxy = (float) MercatorProjection
|
||||||
|
.pixelYToLatitude(pos.y + h, pos.zoomLevel);
|
||||||
|
|
||||||
|
float area = Math.abs((maxx - minx) * (miny - maxy));
|
||||||
|
|
||||||
|
Log.d(TAG, " BBOX " + area + " " + minx + " "
|
||||||
|
+ miny + " " + maxx + " " + maxy);
|
||||||
|
|
||||||
|
w = mMapView.getWidth();
|
||||||
|
h = mMapView.getHeight();
|
||||||
|
mSelected = null;
|
||||||
|
if (mDirection < 0) {
|
||||||
|
// get the next larger bbox, union with current and set view region to it.
|
||||||
|
for (int i = 0, n = boxes.size(); i < n; i++) {
|
||||||
|
BBox bbox = boxes.get(i);
|
||||||
|
if (bbox.area > area || i == n - 1) {
|
||||||
|
mSelected = bbox;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = boxes.size() - 1; i >= 0; i--) {
|
||||||
|
BBox bbox = boxes.get(i);
|
||||||
|
// if (bbox.area < area) {
|
||||||
|
//
|
||||||
|
// double clat = bbox.min.getLatitude()
|
||||||
|
// + (bbox.max.getLatitude() - bbox.min.getLatitude()) / 2;
|
||||||
|
double clon = Math.abs(bbox.max.getLongitude()
|
||||||
|
- bbox.min.getLongitude());
|
||||||
|
|
||||||
|
float zoom = (float) (-Math.log(4) * Math.log(clon / 360) + 0.25);
|
||||||
|
// float scale = 1 + (zoom - FloatMath.floor(zoom));
|
||||||
|
// MapPosition mapPos = new MapPosition(clat,
|
||||||
|
// bbox.min.getLongitude() + clon / 2,
|
||||||
|
// (byte) zoom, 1 + (zoom - FloatMath.floor(zoom)), 0);
|
||||||
|
|
||||||
|
mSelected = bbox;
|
||||||
|
Log.d(TAG, "jump to: " + bbox.name + " " +
|
||||||
|
-Math.log(4) * Math.log(clon / 360) + " " + (byte) zoom);
|
||||||
|
|
||||||
|
if ((byte) zoom > pos.zoomLevel) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mSelected != null) {
|
||||||
|
BBox bbox = mSelected;
|
||||||
|
|
||||||
|
double clat = bbox.min.getLatitude()
|
||||||
|
+ (bbox.max.getLatitude() - bbox.min.getLatitude()) / 2;
|
||||||
|
double clon = Math.abs(bbox.max.getLongitude() - bbox.min.getLongitude());
|
||||||
|
|
||||||
|
Log.d(TAG, "jump to: " + bbox.name + " " +
|
||||||
|
-Math.log(4) * Math.log(clon / 360));
|
||||||
|
|
||||||
|
float zoom = (float) (-Math.log(4) * Math.log(clon / 360) + 0.25);
|
||||||
|
|
||||||
|
MapPosition mapPos = new MapPosition(clat,
|
||||||
|
bbox.min.getLongitude() + clon / 2,
|
||||||
|
(byte) zoom, 1 + (zoom - FloatMath.floor(zoom)), 0);
|
||||||
|
|
||||||
|
mMapView.setMapCenter(mapPos);
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int mDirection;
|
||||||
|
private GeoPoint mPos;
|
||||||
|
|
||||||
|
public synchronized void updateRegion(int direction, GeoPoint pos) {
|
||||||
|
mDirection = direction;
|
||||||
|
mPos = pos;
|
||||||
|
|
||||||
|
new AsyncTask<Object, Integer, Long>() {
|
||||||
|
@Override
|
||||||
|
protected Long doInBackground(Object... params) {
|
||||||
|
RegionLookup.this.updatePosition();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Long result) {
|
||||||
|
// Log.d(TAG, "got sth " + result);
|
||||||
|
if (mSelected != null) {
|
||||||
|
Toast toast = Toast.makeText(mMapView.getContext(), mSelected.name,
|
||||||
|
Toast.LENGTH_SHORT);
|
||||||
|
// toast.setDuration(1000);
|
||||||
|
toast.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}.execute(null, null, null);
|
||||||
|
mSelected = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// private final Handler mHandler = new Handler() {
|
||||||
|
// @Override
|
||||||
|
// public void handleMessage(Message msg) {
|
||||||
|
// Log.d(TAG, "message: " + msg.what);
|
||||||
|
// // switch (msg.what) {
|
||||||
|
// // handle update
|
||||||
|
// // .....
|
||||||
|
// // }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
}
|
@ -29,19 +29,22 @@ import android.view.animation.DecelerateInterpolator;
|
|||||||
import android.widget.Scroller;
|
import android.widget.Scroller;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation for multi-touch capable devices.
|
* Implementation for multi-touch capable devices. TODO write a AnimationTimer instead of using CountDownTimer
|
||||||
*/
|
*/
|
||||||
public class TouchHandler {
|
public class TouchHandler {
|
||||||
private static final int INVALID_POINTER_ID = -1;
|
private static final int INVALID_POINTER_ID = -1;
|
||||||
|
|
||||||
/* package */final MapView mMapView;
|
/* package */final MapView mMapView;
|
||||||
/* package */final MapViewPosition mMapPosition;
|
/* package */final MapViewPosition mMapPosition;
|
||||||
|
/* package */final DecelerateInterpolator mInterpolator = new DecelerateInterpolator();
|
||||||
|
/* package */boolean mBeginScale;
|
||||||
|
/* package */float mSumScale;
|
||||||
|
|
||||||
private final float mMapMoveDelta;
|
private final float mMapMoveDelta;
|
||||||
private boolean mMoveStart;
|
private boolean mMoveStart;
|
||||||
private boolean mRotationStart;
|
private boolean mBeginRotate;
|
||||||
private float mPosX;
|
/* package */float mPosX;
|
||||||
private float mPosY;
|
/* package */float mPosY;
|
||||||
private double mAngle;
|
private double mAngle;
|
||||||
|
|
||||||
private int mActivePointerId;
|
private int mActivePointerId;
|
||||||
@ -78,8 +81,9 @@ public class TouchHandler {
|
|||||||
private boolean onActionDown(MotionEvent event) {
|
private boolean onActionDown(MotionEvent event) {
|
||||||
mPosX = event.getX();
|
mPosX = event.getX();
|
||||||
mPosY = event.getY();
|
mPosY = event.getY();
|
||||||
|
|
||||||
mMoveStart = false;
|
mMoveStart = false;
|
||||||
mRotationStart = false;
|
mBeginRotate = false;
|
||||||
// save the ID of the pointer
|
// save the ID of the pointer
|
||||||
mActivePointerId = event.getPointerId(0);
|
mActivePointerId = event.getPointerId(0);
|
||||||
// Log.d("...", "set active pointer" + mActivePointerId);
|
// Log.d("...", "set active pointer" + mActivePointerId);
|
||||||
@ -126,28 +130,27 @@ public class TouchHandler {
|
|||||||
double dy = y1 - y2;
|
double dy = y1 - y2;
|
||||||
|
|
||||||
double rad = Math.atan2(dy, dx);
|
double rad = Math.atan2(dy, dx);
|
||||||
|
|
||||||
// focus point relative to center
|
|
||||||
double cx = (mMapView.getWidth() >> 1) - (x1 + x2) / 2;
|
|
||||||
double cy = (mMapView.getHeight() >> 1) - (y1 + y2) / 2;
|
|
||||||
double r = rad - mAngle;
|
double r = rad - mAngle;
|
||||||
|
|
||||||
double rsin = Math.sin(r);
|
|
||||||
double rcos = Math.cos(r);
|
|
||||||
|
|
||||||
float x = (float) (cx * rcos + cy * -rsin - cx);
|
|
||||||
float y = (float) (cx * rsin + cy * rcos - cy);
|
|
||||||
|
|
||||||
// Log.d("...", "move " + x + " " + y + " " + cx + " " + cy);
|
// Log.d("...", "move " + x + " " + y + " " + cx + " " + cy);
|
||||||
|
|
||||||
if (!mRotationStart) {
|
if (!mBeginRotate && !mBeginScale) {
|
||||||
if (Math.abs(rad - mAngle) > 0.001)
|
if (r > 0.02 || r < -0.02)
|
||||||
mRotationStart = true;
|
mBeginRotate = true;
|
||||||
}
|
} else if (mBeginRotate) {
|
||||||
else {
|
double rsin = Math.sin(r);
|
||||||
|
double rcos = Math.cos(r);
|
||||||
|
|
||||||
|
// focus point relative to center
|
||||||
|
double cx = (mMapView.getWidth() >> 1) - (x1 + x2) / 2;
|
||||||
|
double cy = (mMapView.getHeight() >> 1) - (y1 + y2) / 2;
|
||||||
|
|
||||||
|
float x = (float) (cx * rcos + cy * -rsin - cx);
|
||||||
|
float y = (float) (cx * rsin + cy * rcos - cy);
|
||||||
|
|
||||||
mMapPosition.rotateMap((float) Math.toDegrees(rad - mAngle), x, y);
|
mMapPosition.rotateMap((float) Math.toDegrees(rad - mAngle), x, y);
|
||||||
mAngle = rad;
|
mAngle = rad;
|
||||||
mMapView.redrawTiles();
|
mMapView.redrawMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,7 +163,7 @@ public class TouchHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mMapPosition.moveMap(moveX, moveY);
|
mMapPosition.moveMap(moveX, moveY);
|
||||||
mMapView.redrawTiles();
|
mMapView.redrawMap();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -182,7 +185,8 @@ public class TouchHandler {
|
|||||||
private boolean onActionPointerUp(MotionEvent motionEvent) {
|
private boolean onActionPointerUp(MotionEvent motionEvent) {
|
||||||
|
|
||||||
// extract the index of the pointer that left the touch sensor
|
// extract the index of the pointer that left the touch sensor
|
||||||
int pointerIndex = (motionEvent.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
|
int masked = (motionEvent.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK);
|
||||||
|
int pointerIndex = masked >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
|
||||||
|
|
||||||
if (motionEvent.getPointerId(pointerIndex) == mActivePointerId) {
|
if (motionEvent.getPointerId(pointerIndex) == mActivePointerId) {
|
||||||
// the active pointer has gone up, choose a new one
|
// the active pointer has gone up, choose a new one
|
||||||
@ -251,7 +255,7 @@ public class TouchHandler {
|
|||||||
|
|
||||||
class MapGestureDetector extends SimpleOnGestureListener {
|
class MapGestureDetector extends SimpleOnGestureListener {
|
||||||
private Scroller mScroller;
|
private Scroller mScroller;
|
||||||
private float mPrevX, mPrevY, mPrevScale;
|
private float mScrollX, mScrollY, mPrevScale;
|
||||||
private CountDownTimer mTimer = null;
|
private CountDownTimer mTimer = null;
|
||||||
private boolean fling = false;
|
private boolean fling = false;
|
||||||
|
|
||||||
@ -282,14 +286,14 @@ public class TouchHandler {
|
|||||||
}
|
}
|
||||||
mScroller.computeScrollOffset();
|
mScroller.computeScrollOffset();
|
||||||
|
|
||||||
float moveX = mScroller.getCurrX() - mPrevX;
|
float moveX = mScroller.getCurrX() - mScrollX;
|
||||||
float moveY = mScroller.getCurrY() - mPrevY;
|
float moveY = mScroller.getCurrY() - mScrollY;
|
||||||
|
|
||||||
if (moveX >= 1 || moveY >= 1 || moveX <= -1 || moveY <= -1) {
|
if (moveX >= 1 || moveY >= 1 || moveX <= -1 || moveY <= -1) {
|
||||||
mMapPosition.moveMap(moveX, moveY);
|
mMapPosition.moveMap(moveX, moveY);
|
||||||
mMapView.redrawTiles();
|
mMapView.redrawMap();
|
||||||
mPrevX = mScroller.getCurrX();
|
mScrollX = mScroller.getCurrX();
|
||||||
mPrevY = mScroller.getCurrY();
|
mScrollY = mScroller.getCurrY();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -299,8 +303,8 @@ public class TouchHandler {
|
|||||||
float velocityY) {
|
float velocityY) {
|
||||||
int w = Tile.TILE_SIZE * 20;
|
int w = Tile.TILE_SIZE * 20;
|
||||||
int h = Tile.TILE_SIZE * 20;
|
int h = Tile.TILE_SIZE * 20;
|
||||||
mPrevX = 0;
|
mScrollX = 0;
|
||||||
mPrevY = 0;
|
mScrollY = 0;
|
||||||
|
|
||||||
if (mTimer != null) {
|
if (mTimer != null) {
|
||||||
mTimer.cancel();
|
mTimer.cancel();
|
||||||
@ -326,61 +330,12 @@ public class TouchHandler {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DecelerateInterpolator mBounce = new DecelerateInterpolator();
|
|
||||||
|
|
||||||
private boolean mZooutOut = true;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLongPress(MotionEvent e) {
|
public void onLongPress(MotionEvent e) {
|
||||||
Log.d("mapsforge", "long press");
|
if (MapView.testRegionZoom) {
|
||||||
|
Log.d("mapsforge", "long press");
|
||||||
mMapView.mRegionLookup.updateRegion();
|
mMapView.mRegionLookup.updateRegion(-1, null);
|
||||||
|
|
||||||
// mMapView.zoom((byte) -1);
|
|
||||||
|
|
||||||
// mPrevScale = 0;
|
|
||||||
|
|
||||||
// mTimer = new CountDownTimer((int) mScaleDuration, 30) {
|
|
||||||
// @Override
|
|
||||||
// public void onTick(long tick) {
|
|
||||||
// scale2(tick);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void onFinish() {
|
|
||||||
// scale2(0);
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }.start();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean scale2(long tick) {
|
|
||||||
|
|
||||||
if (mPrevScale >= 1) {
|
|
||||||
mTimer = null;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float adv = (mScaleDuration - tick) / mScaleDuration;
|
|
||||||
adv = mBounce.getInterpolation(adv);
|
|
||||||
|
|
||||||
float scale = adv - mPrevScale;
|
|
||||||
mPrevScale += scale;
|
|
||||||
|
|
||||||
if (mZooutOut) {
|
|
||||||
mMapPosition.scaleMap(1 - scale, 0, 0);
|
|
||||||
}
|
|
||||||
// } else {
|
|
||||||
// mMapPosition.scaleMap(1 + scale, mFocusX, mFocusY);
|
|
||||||
// }
|
|
||||||
|
|
||||||
mMapView.redrawTiles();
|
|
||||||
|
|
||||||
if (tick == 0)
|
|
||||||
mTimer = null;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final float mScaleDuration = 300;
|
private final float mScaleDuration = 300;
|
||||||
@ -391,7 +346,7 @@ public class TouchHandler {
|
|||||||
if (mPrevScale >= 1)
|
if (mPrevScale >= 1)
|
||||||
return false;
|
return false;
|
||||||
float adv = (mScaleDuration - tick) / mScaleDuration;
|
float adv = (mScaleDuration - tick) / mScaleDuration;
|
||||||
adv = mBounce.getInterpolation(adv);
|
adv = mInterpolator.getInterpolation(adv);
|
||||||
|
|
||||||
float scale = adv - mPrevScale;
|
float scale = adv - mPrevScale;
|
||||||
mPrevScale += scale;
|
mPrevScale += scale;
|
||||||
@ -399,8 +354,8 @@ public class TouchHandler {
|
|||||||
adv += 1;
|
adv += 1;
|
||||||
|
|
||||||
if (scale > 1) {
|
if (scale > 1) {
|
||||||
mMapPosition.scaleMap(scale, mPrevX / adv, mPrevY / adv);
|
mMapPosition.scaleMap(scale, mScrollX / adv, mScrollY / adv);
|
||||||
mMapView.redrawTiles();
|
mMapView.redrawMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -408,24 +363,28 @@ public class TouchHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onDoubleTap(MotionEvent e) {
|
public boolean onDoubleTap(MotionEvent e) {
|
||||||
// Log.d("mapsforge", "double tap");
|
if (MapView.testRegionZoom) {
|
||||||
|
Log.d("mapsforge", "double tap");
|
||||||
|
|
||||||
mPrevX = (e.getX(0) - (mMapView.getWidth() >> 1)) * 2f;
|
mMapView.mRegionLookup.updateRegion(1,
|
||||||
mPrevY = (e.getY(0) - (mMapView.getHeight() >> 1)) * 2f;
|
mMapPosition.getOffsetPoint(mPosX, mPosY));
|
||||||
mPrevScale = 0;
|
} else {
|
||||||
|
mScrollX = (e.getX(0) - (mMapView.getWidth() >> 1)) * 2f;
|
||||||
|
mScrollY = (e.getY(0) - (mMapView.getHeight() >> 1)) * 2f;
|
||||||
|
mPrevScale = 0;
|
||||||
|
|
||||||
mTimer = new CountDownTimer((int) mScaleDuration, 30) {
|
mTimer = new CountDownTimer((int) mScaleDuration, 30) {
|
||||||
@Override
|
@Override
|
||||||
public void onTick(long tick) {
|
public void onTick(long tick) {
|
||||||
scale(tick);
|
scale(tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFinish() {
|
|
||||||
scale(0);
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
scale(0);
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -435,39 +394,35 @@ public class TouchHandler {
|
|||||||
private float mCenterY;
|
private float mCenterY;
|
||||||
private float mFocusX;
|
private float mFocusX;
|
||||||
private float mFocusY;
|
private float mFocusY;
|
||||||
private float mScale;
|
private long mTimeStart;
|
||||||
private boolean mBeginScale;
|
private long mTimeEnd;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onScale(ScaleGestureDetector gd) {
|
public boolean onScale(ScaleGestureDetector gd) {
|
||||||
|
|
||||||
mScale = gd.getScaleFactor();
|
float scale = gd.getScaleFactor();
|
||||||
mFocusX = gd.getFocusX() - mCenterX;
|
mFocusX = gd.getFocusX() - mCenterX;
|
||||||
mFocusY = gd.getFocusY() - mCenterY;
|
mFocusY = gd.getFocusY() - mCenterY;
|
||||||
|
|
||||||
mSumScale *= mScale;
|
mSumScale *= scale;
|
||||||
|
|
||||||
mTimeEnd = SystemClock.elapsedRealtime();
|
mTimeEnd = SystemClock.elapsedRealtime();
|
||||||
|
|
||||||
if (!mBeginScale) {
|
if (!mBeginScale) {
|
||||||
if (mTimeEnd - mTimeStart > 100) {
|
if (mTimeEnd - mTimeStart > 150 || mSumScale > 1.1 || mSumScale < 0.9) {
|
||||||
mBeginScale = true;
|
mBeginScale = true;
|
||||||
mScale = mSumScale;
|
scale = mSumScale;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mMapPosition.scaleMap(mScale, mFocusX, mFocusY);
|
mMapPosition.scaleMap(scale, mFocusX, mFocusY);
|
||||||
mMapView.redrawTiles();
|
mMapView.redrawMap();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long mTimeStart;
|
|
||||||
private long mTimeEnd;
|
|
||||||
private float mSumScale;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onScaleBegin(ScaleGestureDetector gd) {
|
public boolean onScaleBegin(ScaleGestureDetector gd) {
|
||||||
mTimeEnd = mTimeStart = SystemClock.elapsedRealtime();
|
mTimeEnd = mTimeStart = SystemClock.elapsedRealtime();
|
||||||
@ -475,7 +430,6 @@ public class TouchHandler {
|
|||||||
mBeginScale = false;
|
mBeginScale = false;
|
||||||
mCenterX = mMapView.getWidth() >> 1;
|
mCenterX = mMapView.getWidth() >> 1;
|
||||||
mCenterY = mMapView.getHeight() >> 1;
|
mCenterY = mMapView.getHeight() >> 1;
|
||||||
mScale = 1;
|
|
||||||
|
|
||||||
if (mTimer != null) {
|
if (mTimer != null) {
|
||||||
mTimer.cancel();
|
mTimer.cancel();
|
||||||
@ -508,9 +462,9 @@ public class TouchHandler {
|
|||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
}
|
}
|
||||||
|
mBeginScale = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DecelerateInterpolator mBounce = new DecelerateInterpolator();
|
|
||||||
private float mPrevScale;
|
private float mPrevScale;
|
||||||
private CountDownTimer mTimer;
|
private CountDownTimer mTimer;
|
||||||
boolean mZooutOut;
|
boolean mZooutOut;
|
||||||
@ -524,7 +478,7 @@ public class TouchHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float adv = (mScaleDuration - tick) / mScaleDuration;
|
float adv = (mScaleDuration - tick) / mScaleDuration;
|
||||||
adv = mBounce.getInterpolation(adv);
|
adv = mInterpolator.getInterpolation(adv);
|
||||||
|
|
||||||
float scale = adv - mPrevScale;
|
float scale = adv - mPrevScale;
|
||||||
mPrevScale += scale;
|
mPrevScale += scale;
|
||||||
@ -535,7 +489,7 @@ public class TouchHandler {
|
|||||||
mMapPosition.scaleMap(1 + scale, mFocusX, mFocusY);
|
mMapPosition.scaleMap(1 + scale, mFocusX, mFocusY);
|
||||||
}
|
}
|
||||||
|
|
||||||
mMapView.redrawTiles();
|
mMapView.redrawMap();
|
||||||
|
|
||||||
if (tick == 0)
|
if (tick == 0)
|
||||||
mTimer = null;
|
mTimer = null;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.mapgenerator;
|
package org.oscim.view.generator;
|
||||||
|
|
||||||
//import static org.oscim.view.mapgenerator.JobTile.LOADING;
|
//import static org.oscim.view.mapgenerator.JobTile.LOADING;
|
||||||
|
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.mapgenerator;
|
package org.oscim.view.generator;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
|
|
@ -12,9 +12,11 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.mapgenerator;
|
package org.oscim.view.generator;
|
||||||
|
|
||||||
import org.oscim.view.IMapRenderer;
|
import org.oscim.utils.PausableThread;
|
||||||
|
import org.oscim.view.renderer.MapGenerator;
|
||||||
|
import org.oscim.view.renderer.MapRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A MapWorker uses a {@link IMapGenerator} to generate map tiles. It runs in a separate thread to avoid blocking the UI
|
* A MapWorker uses a {@link IMapGenerator} to generate map tiles. It runs in a separate thread to avoid blocking the UI
|
||||||
@ -23,8 +25,8 @@ import org.oscim.view.IMapRenderer;
|
|||||||
public class MapWorker extends PausableThread {
|
public class MapWorker extends PausableThread {
|
||||||
private final String THREAD_NAME;
|
private final String THREAD_NAME;
|
||||||
private final JobQueue mJobQueue;
|
private final JobQueue mJobQueue;
|
||||||
private final IMapGenerator mMapGenerator;
|
private final MapGenerator mMapGenerator;
|
||||||
private final IMapRenderer mMapRenderer;
|
private final MapRenderer mMapRenderer;
|
||||||
|
|
||||||
// private final int mPrio;
|
// private final int mPrio;
|
||||||
|
|
||||||
@ -36,8 +38,8 @@ public class MapWorker extends PausableThread {
|
|||||||
* @param mapRenderer
|
* @param mapRenderer
|
||||||
* ...
|
* ...
|
||||||
*/
|
*/
|
||||||
public MapWorker(int id, JobQueue jobQueue, IMapGenerator mapGenerator,
|
public MapWorker(int id, JobQueue jobQueue, MapGenerator mapGenerator,
|
||||||
IMapRenderer mapRenderer) {
|
MapRenderer mapRenderer) {
|
||||||
super();
|
super();
|
||||||
mJobQueue = jobQueue;
|
mJobQueue = jobQueue;
|
||||||
mMapGenerator = mapGenerator;
|
mMapGenerator = mapGenerator;
|
||||||
@ -47,7 +49,7 @@ public class MapWorker extends PausableThread {
|
|||||||
// mPrio = Math.max(Thread.MIN_PRIORITY + id, Thread.NORM_PRIORITY - 1);
|
// mPrio = Math.max(Thread.MIN_PRIORITY + id, Thread.NORM_PRIORITY - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMapGenerator getMapGenerator() {
|
public MapGenerator getMapGenerator() {
|
||||||
return mMapGenerator;
|
return mMapGenerator;
|
||||||
}
|
}
|
||||||
|
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.mapgenerator;
|
package org.oscim.view.generator;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 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 License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.glrenderer;
|
|
||||||
|
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
|
||||||
|
|
||||||
class MapTile extends JobTile {
|
|
||||||
byte lastDraw = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VBO layout:
|
|
||||||
* - 16 bytes fill coordinates
|
|
||||||
* - n bytes polygon vertices
|
|
||||||
* - m bytes lines vertices
|
|
||||||
*/
|
|
||||||
VertexBufferObject vbo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* polygonOffset in vbo is always 16 bytes,
|
|
||||||
*/
|
|
||||||
int lineOffset;
|
|
||||||
|
|
||||||
TextTexture texture;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tile data set by MapGenerator:
|
|
||||||
*/
|
|
||||||
LineLayer lineLayers;
|
|
||||||
PolygonLayer polygonLayers;
|
|
||||||
TextItem labels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* tile has new data to upload to gl
|
|
||||||
*/
|
|
||||||
boolean newData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* tile is loaded and ready for drawing.
|
|
||||||
*/
|
|
||||||
boolean isReady;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* tile is in view region.
|
|
||||||
*/
|
|
||||||
boolean isVisible;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* tile is used by render thread. set by updateVisibleList (main thread).
|
|
||||||
*/
|
|
||||||
boolean isActive;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pointer to access relatives in TileTree
|
|
||||||
*/
|
|
||||||
QuadTree rel;
|
|
||||||
|
|
||||||
MapTile(int tileX, int tileY, byte zoomLevel) {
|
|
||||||
super(tileX, tileY, zoomLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.mapgenerator;
|
|
||||||
|
|
||||||
import org.oscim.database.IMapDatabase;
|
|
||||||
import org.oscim.theme.RenderTheme;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A MapGenerator provides map tiles either by downloading or rendering them.
|
|
||||||
*/
|
|
||||||
public interface IMapGenerator {
|
|
||||||
/**
|
|
||||||
* Called once at the end of the MapGenerator lifecycle.
|
|
||||||
*/
|
|
||||||
void cleanup();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a job needs to be executed.
|
|
||||||
*
|
|
||||||
* @param tile
|
|
||||||
* the job that should be executed.
|
|
||||||
* @return true if the job was executed successfully, false otherwise.
|
|
||||||
*/
|
|
||||||
boolean executeJob(JobTile tile);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mapDatabase
|
|
||||||
* the MapDatabase from which the map data will be read.
|
|
||||||
*/
|
|
||||||
void setMapDatabase(IMapDatabase mapDatabase);
|
|
||||||
|
|
||||||
IMapDatabase getMapDatabase();
|
|
||||||
|
|
||||||
void setRenderTheme(RenderTheme theme);
|
|
||||||
}
|
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General License along with
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
import static android.opengl.GLES20.GL_ARRAY_BUFFER;
|
import static android.opengl.GLES20.GL_ARRAY_BUFFER;
|
||||||
import static android.opengl.GLES20.GL_BLEND;
|
import static android.opengl.GLES20.GL_BLEND;
|
||||||
@ -41,20 +41,19 @@ import javax.microedition.khronos.opengles.GL10;
|
|||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.theme.RenderTheme;
|
import org.oscim.theme.RenderTheme;
|
||||||
|
import org.oscim.utils.GlUtils;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
import org.oscim.view.mapgenerator.IMapGenerator;
|
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
|
||||||
import org.oscim.view.utils.GlUtils;
|
|
||||||
|
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
|
import android.opengl.GLSurfaceView;
|
||||||
import android.opengl.Matrix;
|
import android.opengl.Matrix;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.FloatMath;
|
import android.util.FloatMath;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class MapRenderer implements org.oscim.view.IMapRenderer {
|
public class GLRenderer implements GLSurfaceView.Renderer {
|
||||||
|
|
||||||
private static final String TAG = "MapRenderer";
|
private static final String TAG = "SurfaceRenderer";
|
||||||
|
|
||||||
private static final int MB = 1024 * 1024;
|
private static final int MB = 1024 * 1024;
|
||||||
private static final int SHORT_BYTES = 2;
|
private static final int SHORT_BYTES = 2;
|
||||||
@ -117,7 +116,7 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
* @param mapView
|
* @param mapView
|
||||||
* the MapView
|
* the MapView
|
||||||
*/
|
*/
|
||||||
public MapRenderer(MapView mapView) {
|
public GLRenderer(MapView mapView) {
|
||||||
Log.d(TAG, "init MapRenderer");
|
Log.d(TAG, "init MapRenderer");
|
||||||
|
|
||||||
mMapView = mapView;
|
mMapView = mapView;
|
||||||
@ -126,17 +125,6 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
mUpdateTiles = false;
|
mUpdateTiles = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* called by MapView when position or map settings changes
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void updateMap(boolean clear) {
|
|
||||||
if (mWidth <= 0 || mHeight <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TileLoader.updateMap(clear);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called by TileLoader when only position changed
|
* called by TileLoader when only position changed
|
||||||
*
|
*
|
||||||
@ -157,21 +145,51 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
* @return curTiles (the previously active tiles)
|
* @return curTiles (the previously active tiles)
|
||||||
*/
|
*/
|
||||||
static TilesData updateTiles(MapPosition mapPosition, TilesData tiles) {
|
static TilesData updateTiles(MapPosition mapPosition, TilesData tiles) {
|
||||||
synchronized (MapRenderer.lock) {
|
synchronized (GLRenderer.lock) {
|
||||||
|
|
||||||
mCurPosition = mapPosition;
|
mCurPosition = mapPosition;
|
||||||
|
|
||||||
for (int i = 0; i < curTiles.cnt; i++)
|
// unlock previously active tiles
|
||||||
curTiles.tiles[i].isActive = false;
|
for (int i = 0; i < curTiles.cnt; i++) {
|
||||||
|
MapTile t = curTiles.tiles[i];
|
||||||
|
boolean found = false;
|
||||||
|
|
||||||
|
for (int j = 0; j < tiles.cnt; j++) {
|
||||||
|
if (tiles.tiles[j] == t) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int j = 0; j < drawTiles.cnt; j++) {
|
||||||
|
if (drawTiles.tiles[j] == t) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
t.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
TilesData tmp = curTiles;
|
TilesData tmp = curTiles;
|
||||||
curTiles = tiles;
|
curTiles = tiles;
|
||||||
|
|
||||||
for (int i = 0; i < curTiles.cnt; i++)
|
// lock tiles (and their proxies) to not be removed from cache
|
||||||
curTiles.tiles[i].isActive = true;
|
for (int i = 0; i < curTiles.cnt; i++) {
|
||||||
|
MapTile t = curTiles.tiles[i];
|
||||||
|
if (!t.isActive)
|
||||||
|
t.lock();
|
||||||
|
}
|
||||||
|
|
||||||
for (int j = 0; j < drawTiles.cnt; j++)
|
for (int j = 0; j < drawTiles.cnt; j++) {
|
||||||
drawTiles.tiles[j].isActive = true;
|
MapTile t = drawTiles.tiles[j];
|
||||||
|
if (!t.isActive)
|
||||||
|
t.lock();
|
||||||
|
}
|
||||||
|
|
||||||
mUpdateTiles = true;
|
mUpdateTiles = true;
|
||||||
|
|
||||||
@ -191,44 +209,25 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void setVBO(MapTile tile) {
|
||||||
* called from MapWorker Thread when tile is loaded by MapGenerator
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public synchronized boolean passTile(JobTile jobTile) {
|
|
||||||
MapTile tile = (MapTile) jobTile;
|
|
||||||
|
|
||||||
if (!tile.isLoading) {
|
|
||||||
// no one should be able to use this tile now, mapgenerator passed it,
|
|
||||||
// glthread does nothing until newdata is set.
|
|
||||||
Log.d(TAG, "passTile: canceled " + tile);
|
|
||||||
TileLoader.addTileLoaded(tile);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (mVBOs) {
|
synchronized (mVBOs) {
|
||||||
int numVBOs = mVBOs.size();
|
int numVBOs = mVBOs.size();
|
||||||
|
|
||||||
if (numVBOs > 0 && tile.vbo == null) {
|
if (numVBOs > 0 && tile.vbo == null) {
|
||||||
tile.vbo = mVBOs.remove(numVBOs - 1);
|
tile.vbo = mVBOs.remove(numVBOs - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tile.vbo == null) {
|
|
||||||
Log.d(TAG, "no VBOs left for " + tile);
|
|
||||||
tile.isLoading = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tile.newData = true;
|
void setRenderTheme(RenderTheme t) {
|
||||||
tile.isLoading = false;
|
int bg = t.getMapBackground();
|
||||||
|
float[] c = new float[4];
|
||||||
if (!MapView.debugFrameTime)
|
c[3] = (bg >> 24 & 0xff) / 255.0f;
|
||||||
mMapView.requestRender();
|
c[0] = (bg >> 16 & 0xff) / 255.0f;
|
||||||
|
c[1] = (bg >> 8 & 0xff) / 255.0f;
|
||||||
TileLoader.addTileLoaded(tile);
|
c[2] = (bg >> 0 & 0xff) / 255.0f;
|
||||||
|
mClearColor = c;
|
||||||
return true;
|
mUpdateColor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// depthRange: -1 to 1, bits: 2^24 => 2/2^24 one step
|
// depthRange: -1 to 1, bits: 2^24 => 2/2^24 one step
|
||||||
@ -254,7 +253,7 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
Matrix.translateM(mMVPMatrix, 0,
|
Matrix.translateM(mMVPMatrix, 0,
|
||||||
x * COORD_MULTIPLIER,
|
x * COORD_MULTIPLIER,
|
||||||
-(y + Tile.TILE_SIZE) * COORD_MULTIPLIER,
|
-(y + Tile.TILE_SIZE) * COORD_MULTIPLIER,
|
||||||
-1 + offset * 0.01f);
|
-0.99f + offset * 0.01f);
|
||||||
|
|
||||||
Matrix.multiplyMM(mMVPMatrix, 0, mRotateMatrix, 0, mMVPMatrix, 0);
|
Matrix.multiplyMM(mMVPMatrix, 0, mRotateMatrix, 0, mMVPMatrix, 0);
|
||||||
|
|
||||||
@ -268,7 +267,7 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
mMVPMatrix[12] = x * scale * mAspect;
|
mMVPMatrix[12] = x * scale * mAspect;
|
||||||
mMVPMatrix[13] = -(y + Tile.TILE_SIZE) * scale;
|
mMVPMatrix[13] = -(y + Tile.TILE_SIZE) * scale;
|
||||||
// increase the 'distance' with each tile drawn.
|
// increase the 'distance' with each tile drawn.
|
||||||
mMVPMatrix[14] = -1 + offset * 0.01f; // depthStep; // 0.01f;
|
mMVPMatrix[14] = -0.99f + offset * 0.01f; // depthStep; // 0.01f;
|
||||||
mMVPMatrix[0] = scale * mAspect / COORD_MULTIPLIER;
|
mMVPMatrix[0] = scale * mAspect / COORD_MULTIPLIER;
|
||||||
mMVPMatrix[5] = scale / COORD_MULTIPLIER;
|
mMVPMatrix[5] = scale / COORD_MULTIPLIER;
|
||||||
}
|
}
|
||||||
@ -332,13 +331,13 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
if (!tile.newData)
|
if (!tile.newData)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int lineSize = LineLayers.sizeOf(tile.lineLayers);
|
int lineSize = LineRenderer.sizeOf(tile.lineLayers);
|
||||||
int polySize = PolygonLayers.sizeOf(tile.polygonLayers);
|
int polySize = PolygonRenderer.sizeOf(tile.polygonLayers);
|
||||||
int newSize = lineSize + polySize;
|
int newSize = lineSize + polySize;
|
||||||
|
|
||||||
if (newSize == 0) {
|
if (newSize == 0) {
|
||||||
LineLayers.clear(tile.lineLayers);
|
LineRenderer.clear(tile.lineLayers);
|
||||||
PolygonLayers.clear(tile.polygonLayers);
|
PolygonRenderer.clear(tile.polygonLayers);
|
||||||
tile.lineLayers = null;
|
tile.lineLayers = null;
|
||||||
tile.polygonLayers = null;
|
tile.polygonLayers = null;
|
||||||
tile.newData = false;
|
tile.newData = false;
|
||||||
@ -365,7 +364,7 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
sbuf.clear();
|
sbuf.clear();
|
||||||
sbuf.position(8);
|
sbuf.position(8);
|
||||||
|
|
||||||
PolygonLayers.compileLayerData(tile.polygonLayers, sbuf);
|
PolygonRenderer.compileLayerData(tile.polygonLayers, sbuf);
|
||||||
|
|
||||||
tile.lineOffset = (8 + polySize);
|
tile.lineOffset = (8 + polySize);
|
||||||
if (tile.lineOffset != sbuf.position())
|
if (tile.lineOffset != sbuf.position())
|
||||||
@ -374,25 +373,29 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
+ sbuf.position() + " "
|
+ sbuf.position() + " "
|
||||||
+ sbuf.limit() + " "
|
+ sbuf.limit() + " "
|
||||||
+ sbuf.remaining() + " "
|
+ sbuf.remaining() + " "
|
||||||
+ PolygonLayers.sizeOf(tile.polygonLayers) + " "
|
+ PolygonRenderer.sizeOf(tile.polygonLayers) + " "
|
||||||
+ tile.rel);
|
+ tile.rel);
|
||||||
|
|
||||||
tile.lineOffset *= SHORT_BYTES;
|
tile.lineOffset *= SHORT_BYTES;
|
||||||
|
|
||||||
LineLayers.compileLayerData(tile.lineLayers, sbuf);
|
LineRenderer.compileLayerData(tile.lineLayers, sbuf);
|
||||||
|
|
||||||
sbuf.flip();
|
sbuf.flip();
|
||||||
|
|
||||||
if (newSize != sbuf.remaining())
|
if (newSize != sbuf.remaining()) {
|
||||||
|
|
||||||
Log.d(TAG, "tiles wrong: " + tile + " "
|
Log.d(TAG, "tiles wrong: " + tile + " "
|
||||||
+ newSize + " "
|
+ newSize + " "
|
||||||
+ sbuf.position() + " "
|
+ sbuf.position() + " "
|
||||||
+ sbuf.limit() + " "
|
+ sbuf.limit() + " "
|
||||||
+ sbuf.remaining() + " "
|
+ sbuf.remaining() + " "
|
||||||
+ LineLayers.sizeOf(tile.lineLayers)
|
+ LineRenderer.sizeOf(tile.lineLayers)
|
||||||
+ tile.isLoading + " "
|
+ tile.isLoading + " "
|
||||||
+ tile.rel);
|
+ tile.rel);
|
||||||
|
|
||||||
|
tile.newData = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
newSize *= SHORT_BYTES;
|
newSize *= SHORT_BYTES;
|
||||||
|
|
||||||
if (tile.vbo.size > newSize && tile.vbo.size < newSize * 4
|
if (tile.vbo.size > newSize && tile.vbo.size < newSize * 4
|
||||||
@ -459,6 +462,7 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
@Override
|
@Override
|
||||||
public void onDrawFrame(GL10 glUnused) {
|
public void onDrawFrame(GL10 glUnused) {
|
||||||
long start = 0;
|
long start = 0;
|
||||||
|
|
||||||
MapPosition mapPosition;
|
MapPosition mapPosition;
|
||||||
|
|
||||||
if (MapView.debugFrameTime)
|
if (MapView.debugFrameTime)
|
||||||
@ -484,7 +488,7 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
| GLES20.GL_STENCIL_BUFFER_BIT);
|
| GLES20.GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
// get position and current tiles to draw
|
// get position and current tiles to draw
|
||||||
synchronized (MapRenderer.lock) {
|
synchronized (GLRenderer.lock) {
|
||||||
mapPosition = mCurPosition;
|
mapPosition = mCurPosition;
|
||||||
|
|
||||||
if (mUpdateTiles) {
|
if (mUpdateTiles) {
|
||||||
@ -495,6 +499,9 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (drawTiles == null)
|
||||||
|
return;
|
||||||
|
|
||||||
int tileCnt = drawTiles.cnt;
|
int tileCnt = drawTiles.cnt;
|
||||||
MapTile[] tiles = drawTiles.tiles;
|
MapTile[] tiles = drawTiles.tiles;
|
||||||
|
|
||||||
@ -635,24 +642,25 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
if (pl != null && pnext < lnext) {
|
if (pl != null && pnext < lnext) {
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
pl = PolygonLayers.drawPolygons(pl, lnext, mMVPMatrix, z, s, !clipped);
|
pl = PolygonRenderer.drawPolygons(pl, lnext, mMVPMatrix, z, s, !clipped);
|
||||||
|
|
||||||
clipped = true;
|
clipped = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// XXX nasty
|
// XXX nasty
|
||||||
if (!clipped) {
|
if (!clipped) {
|
||||||
PolygonLayers.drawPolygons(null, 0, mMVPMatrix, z, s, true);
|
PolygonRenderer.drawPolygons(null, 0, mMVPMatrix, z, s, true);
|
||||||
clipped = true;
|
clipped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
ll = LineLayers.drawLines(tile, ll, pnext, mMVPMatrix, div, z, s);
|
ll = LineRenderer.drawLines(tile, ll, pnext, mMVPMatrix, div, z, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO could use tile.proxies here
|
||||||
private static boolean drawProxyChild(MapPosition mapPosition, MapTile tile) {
|
private static boolean drawProxyChild(MapPosition mapPosition, MapTile tile) {
|
||||||
int drawn = 0;
|
int drawn = 0;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
@ -676,6 +684,7 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
return drawn == 4;
|
return drawn == 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO could use tile.proxies here
|
||||||
private static void drawProxyTile(MapPosition mapPosition, MapTile tile) {
|
private static void drawProxyTile(MapPosition mapPosition, MapTile tile) {
|
||||||
|
|
||||||
if (mapPosition.scale > 1.5f) {
|
if (mapPosition.scale > 1.5f) {
|
||||||
@ -716,14 +725,16 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
|
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
|
||||||
Log.d(TAG, "SurfaceChanged:" + width + " " + height);
|
Log.d(TAG, "SurfaceChanged:" + width + " " + height);
|
||||||
|
|
||||||
drawTiles = curTiles = null;
|
mWidth = width;
|
||||||
mBufferMemoryUsage = 0;
|
mHeight = height;
|
||||||
|
|
||||||
if (width <= 0 || height <= 0)
|
if (width <= 0 || height <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mWidth = width;
|
boolean changed = true;
|
||||||
mHeight = height;
|
if (mWidth == width || mHeight == height)
|
||||||
|
changed = false;
|
||||||
|
|
||||||
mAspect = (float) height / width;
|
mAspect = (float) height / width;
|
||||||
|
|
||||||
Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f, 0.5f, -1, 1);
|
Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f, 0.5f, -1, 1);
|
||||||
@ -733,14 +744,16 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
|
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
|
|
||||||
|
if (!changed && !mNewSurface) {
|
||||||
|
mMapView.redrawMap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mBufferMemoryUsage = 0;
|
||||||
|
|
||||||
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
|
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
|
||||||
* (mHeight / (Tile.TILE_SIZE / 2) + 2);
|
* (mHeight / (Tile.TILE_SIZE / 2) + 2);
|
||||||
|
|
||||||
TileLoader.init(mMapView, width, height, numTiles);
|
|
||||||
|
|
||||||
drawTiles = new TilesData(numTiles);
|
|
||||||
curTiles = new TilesData(numTiles);
|
|
||||||
|
|
||||||
// Set up vertex buffer objects
|
// Set up vertex buffer objects
|
||||||
int numVBO = (CACHE_TILES + (numTiles * 2));
|
int numVBO = (CACHE_TILES + (numTiles * 2));
|
||||||
int[] mVboIds = new int[numVBO];
|
int[] mVboIds = new int[numVBO];
|
||||||
@ -774,14 +787,24 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
|
|
||||||
GlUtils.checkGlError("onSurfaceChanged");
|
GlUtils.checkGlError("onSurfaceChanged");
|
||||||
|
|
||||||
mMapView.redrawTiles();
|
mMapView.redrawMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearTiles() {
|
||||||
|
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
|
||||||
|
* (mHeight / (Tile.TILE_SIZE / 2) + 2);
|
||||||
|
|
||||||
|
Log.d(TAG, "clearTiles " + numTiles);
|
||||||
|
|
||||||
|
drawTiles = new TilesData(numTiles);
|
||||||
|
curTiles = new TilesData(numTiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||||
|
|
||||||
// String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
||||||
// Log.d(TAG, "Extensions: " + ext);
|
Log.d(TAG, "Extensions: " + ext);
|
||||||
|
|
||||||
shortBuffer = new ShortBuffer[rotateBuffers];
|
shortBuffer = new ShortBuffer[rotateBuffers];
|
||||||
|
|
||||||
@ -799,25 +822,11 @@ public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|||||||
mFillCoords[6] = max;
|
mFillCoords[6] = max;
|
||||||
mFillCoords[7] = min;
|
mFillCoords[7] = min;
|
||||||
|
|
||||||
LineLayers.init();
|
LineRenderer.init();
|
||||||
PolygonLayers.init();
|
PolygonRenderer.init();
|
||||||
|
mNewSurface = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private boolean mNewSurface;
|
||||||
public IMapGenerator createMapGenerator() {
|
|
||||||
return new MapGenerator(mMapView);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRenderTheme(RenderTheme t) {
|
|
||||||
int bg = t.getMapBackground();
|
|
||||||
float[] c = new float[4];
|
|
||||||
c[0] = (bg >> 16 & 0xff) / 255.0f;
|
|
||||||
c[1] = (bg >> 8 & 0xff) / 255.0f;
|
|
||||||
c[2] = (bg >> 0 & 0xff) / 255.0f;
|
|
||||||
c[3] = (bg >> 24 & 0xff) / 255.0f;
|
|
||||||
mClearColor = c;
|
|
||||||
mUpdateColor = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General License along with
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.theme.renderinstruction.Line;
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
@ -22,7 +22,7 @@ import android.util.FloatMath;
|
|||||||
|
|
||||||
class LineLayer {
|
class LineLayer {
|
||||||
|
|
||||||
private static final float COORD_SCALE = MapRenderer.COORD_MULTIPLIER;
|
private static final float COORD_SCALE = GLRenderer.COORD_MULTIPLIER;
|
||||||
// scale factor mapping extrusion vector to short values
|
// scale factor mapping extrusion vector to short values
|
||||||
private static final float DIR_SCALE = 2048;
|
private static final float DIR_SCALE = 2048;
|
||||||
// mask for packing last two bits of extrusion vector with texture coordinates
|
// mask for packing last two bits of extrusion vector with texture coordinates
|
||||||
@ -67,7 +67,7 @@ class LineLayer {
|
|||||||
* line extrusion is based on code from GLMap (https://github.com/olofsj/GLMap/) by olofsj
|
* line extrusion is based on code from GLMap (https://github.com/olofsj/GLMap/) by olofsj
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void addLine(float[] points, short[] index) {
|
void addLine(float[] points, short[] index, boolean closed) {
|
||||||
float x, y, nextX, nextY, prevX, prevY;
|
float x, y, nextX, nextY, prevX, prevY;
|
||||||
float a, ux, uy, vx, vy, wx, wy;
|
float a, ux, uy, vx, vy, wx, wy;
|
||||||
|
|
||||||
@ -91,6 +91,7 @@ class LineLayer {
|
|||||||
int opos = si.used;
|
int opos = si.used;
|
||||||
|
|
||||||
for (int i = 0, pos = 0, n = index.length; i < n; i++) {
|
for (int i = 0, pos = 0, n = index.length; i < n; i++) {
|
||||||
|
|
||||||
int length = index[i];
|
int length = index[i];
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
break;
|
break;
|
||||||
@ -99,15 +100,22 @@ class LineLayer {
|
|||||||
if (rounded && i > 200)
|
if (rounded && i > 200)
|
||||||
rounded = false;
|
rounded = false;
|
||||||
|
|
||||||
int ipos = pos;
|
|
||||||
|
|
||||||
// need at least two points
|
// need at least two points
|
||||||
if (length < 4) {
|
if (length < 4) {
|
||||||
pos += length;
|
pos += length;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
closed = false;
|
||||||
|
|
||||||
// amount of vertices used
|
// amount of vertices used
|
||||||
verticesCnt += length + (rounded ? 6 : 2);
|
// + 2 for drawing triangle-strip
|
||||||
|
// + 4 for round caps
|
||||||
|
// + 2 for closing polygons
|
||||||
|
verticesCnt += length + (rounded ? 6 : 2) + (closed ? 2 : 0);
|
||||||
|
|
||||||
|
int ipos = pos;
|
||||||
|
|
||||||
x = points[ipos++];
|
x = points[ipos++];
|
||||||
y = points[ipos++];
|
y = points[ipos++];
|
||||||
@ -270,9 +278,17 @@ class LineLayer {
|
|||||||
x = nextX;
|
x = nextX;
|
||||||
y = nextY;
|
y = nextY;
|
||||||
|
|
||||||
for (; ipos < pos + length;) {
|
for (;;) {
|
||||||
nextX = points[ipos++];
|
if (ipos < pos + length) {
|
||||||
nextY = points[ipos++];
|
nextX = points[ipos++];
|
||||||
|
nextY = points[ipos++];
|
||||||
|
} else if (closed && ipos < pos + length + 2) {
|
||||||
|
// add startpoint == endpoint
|
||||||
|
nextX = points[pos];
|
||||||
|
nextY = points[pos + 1];
|
||||||
|
ipos += 2;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
|
||||||
// Unit vector pointing back to previous node
|
// Unit vector pointing back to previous node
|
||||||
vx = prevX - x;
|
vx = prevX - x;
|
||||||
@ -310,18 +326,18 @@ class LineLayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opos == ShortItem.SIZE) {
|
|
||||||
si = si.next = ShortPool.get();
|
|
||||||
v = si.vertices;
|
|
||||||
opos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ox = (short) (x * COORD_SCALE);
|
ox = (short) (x * COORD_SCALE);
|
||||||
oy = (short) (y * COORD_SCALE);
|
oy = (short) (y * COORD_SCALE);
|
||||||
|
|
||||||
ddx = (int) (ux * DIR_SCALE);
|
ddx = (int) (ux * DIR_SCALE);
|
||||||
ddy = (int) (uy * DIR_SCALE);
|
ddy = (int) (uy * DIR_SCALE);
|
||||||
|
|
||||||
|
if (opos == ShortItem.SIZE) {
|
||||||
|
si = si.next = ShortPool.get();
|
||||||
|
v = si.vertices;
|
||||||
|
opos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
v[opos++] = ox;
|
v[opos++] = ox;
|
||||||
v[opos++] = oy;
|
v[opos++] = oy;
|
||||||
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General License along with
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
import static android.opengl.GLES20.GL_TRIANGLE_STRIP;
|
import static android.opengl.GLES20.GL_TRIANGLE_STRIP;
|
||||||
import static android.opengl.GLES20.glDisableVertexAttribArray;
|
import static android.opengl.GLES20.glDisableVertexAttribArray;
|
||||||
@ -20,8 +20,6 @@ import static android.opengl.GLES20.glDrawArrays;
|
|||||||
import static android.opengl.GLES20.glEnableVertexAttribArray;
|
import static android.opengl.GLES20.glEnableVertexAttribArray;
|
||||||
import static android.opengl.GLES20.glGetAttribLocation;
|
import static android.opengl.GLES20.glGetAttribLocation;
|
||||||
import static android.opengl.GLES20.glGetUniformLocation;
|
import static android.opengl.GLES20.glGetUniformLocation;
|
||||||
import static android.opengl.GLES20.glUniform4f;
|
|
||||||
import static android.opengl.GLES20.glUniform4fv;
|
|
||||||
import static android.opengl.GLES20.glUniformMatrix4fv;
|
import static android.opengl.GLES20.glUniformMatrix4fv;
|
||||||
import static android.opengl.GLES20.glUseProgram;
|
import static android.opengl.GLES20.glUseProgram;
|
||||||
import static android.opengl.GLES20.glVertexAttribPointer;
|
import static android.opengl.GLES20.glVertexAttribPointer;
|
||||||
@ -29,12 +27,12 @@ import static android.opengl.GLES20.glVertexAttribPointer;
|
|||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
import org.oscim.theme.renderinstruction.Line;
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
import org.oscim.view.utils.GlUtils;
|
import org.oscim.utils.GlUtils;
|
||||||
|
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
import android.util.FloatMath;
|
import android.util.FloatMath;
|
||||||
|
|
||||||
class LineLayers {
|
class LineRenderer {
|
||||||
private static int NUM_VERTEX_SHORTS = 4;
|
private static int NUM_VERTEX_SHORTS = 4;
|
||||||
|
|
||||||
private static final int LINE_VERTICES_DATA_POS_OFFSET = 0;
|
private static final int LINE_VERTICES_DATA_POS_OFFSET = 0;
|
||||||
@ -108,20 +106,12 @@ class LineLayers {
|
|||||||
if (line.fade != -1 && line.fade > zoom)
|
if (line.fade != -1 && line.fade > zoom)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (line.fade >= zoom) {
|
float alpha = 1.0f;
|
||||||
float alpha = 1.0f;
|
|
||||||
|
|
||||||
|
if (line.fade >= zoom)
|
||||||
alpha = (scale > 1.2f ? scale : 1.2f) - alpha;
|
alpha = (scale > 1.2f ? scale : 1.2f) - alpha;
|
||||||
if (alpha > 1.0f)
|
|
||||||
alpha = 1.0f;
|
GlUtils.setColor(hLineColor, line.color, alpha);
|
||||||
glUniform4f(hLineColor,
|
|
||||||
line.color[0] * alpha,
|
|
||||||
line.color[1] * alpha,
|
|
||||||
line.color[2] * alpha,
|
|
||||||
alpha);
|
|
||||||
} else {
|
|
||||||
glUniform4fv(hLineColor, 1, line.color, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blur) {
|
if (blur) {
|
||||||
if (mFast)
|
if (mFast)
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
import org.oscim.core.MercatorProjection;
|
import org.oscim.core.MercatorProjection;
|
||||||
import org.oscim.core.Tag;
|
import org.oscim.core.Tag;
|
||||||
@ -30,8 +30,7 @@ import org.oscim.theme.renderinstruction.PathText;
|
|||||||
import org.oscim.theme.renderinstruction.RenderInstruction;
|
import org.oscim.theme.renderinstruction.RenderInstruction;
|
||||||
import org.oscim.view.DebugSettings;
|
import org.oscim.view.DebugSettings;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
import org.oscim.view.mapgenerator.IMapGenerator;
|
import org.oscim.view.generator.JobTile;
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
@ -40,7 +39,7 @@ import android.util.Log;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabaseCallback {
|
public class MapGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||||
|
|
||||||
private static String TAG = MapGenerator.class.getName();
|
private static String TAG = MapGenerator.class.getName();
|
||||||
|
|
||||||
@ -59,8 +58,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
|
|
||||||
private MapTile mCurrentTile;
|
private MapTile mCurrentTile;
|
||||||
|
|
||||||
private float[] mWayNodes;
|
private float[] mCoords;
|
||||||
private short[] mWays;
|
private short[] mIndices;
|
||||||
|
|
||||||
private LineLayer mLineLayers;
|
private LineLayer mLineLayers;
|
||||||
private PolygonLayer mPolyLayers;
|
private PolygonLayer mPolyLayers;
|
||||||
@ -89,8 +88,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
private final Tag[] debugTagWay = { new Tag("debug", "way") };
|
private final Tag[] debugTagWay = { new Tag("debug", "way") };
|
||||||
private final Tag[] debugTagArea = { new Tag("debug", "area") };
|
private final Tag[] debugTagArea = { new Tag("debug", "area") };
|
||||||
private final float[] debugBoxCoords = { 0, 0, 0, Tile.TILE_SIZE,
|
private final float[] debugBoxCoords = { 0, 0, 0, Tile.TILE_SIZE,
|
||||||
Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE, 0, 0, 0 };
|
Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE, 0 };
|
||||||
private final short[] debugBoxIndex = { 10 };
|
private final short[] debugBoxIndex = { 8 };
|
||||||
|
|
||||||
private float mProjectionScaleFactor;
|
private float mProjectionScaleFactor;
|
||||||
|
|
||||||
@ -112,7 +111,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
private void filterTags(Tag[] tags) {
|
private void filterTags(Tag[] tags) {
|
||||||
for (int i = 0; i < tags.length; i++) {
|
for (int i = 0; i < tags.length; i++) {
|
||||||
// Log.d(TAG, "check tag: " + tags[i]);
|
// Log.d(TAG, "check tag: " + tags[i]);
|
||||||
if (tags[i].key == Tag.TAG_KEY_NAME && tags[i].value != null) {
|
if (tags[i].key == Tag.TAG_KEY_NAME) {
|
||||||
mTagName = tags[i];
|
mTagName = tags[i];
|
||||||
tags[i] = mTagEmptyName;
|
tags[i] = mTagEmptyName;
|
||||||
}
|
}
|
||||||
@ -122,8 +121,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
// private RenderInstruction[] mNodeRenderInstructions;
|
// private RenderInstruction[] mNodeRenderInstructions;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderPointOfInterest(byte layer, float latitude, float longitude,
|
public void renderPointOfInterest(byte layer, Tag[] tags, float latitude,
|
||||||
Tag[] tags) {
|
float longitude) {
|
||||||
|
|
||||||
mTagName = null;
|
mTagName = null;
|
||||||
|
|
||||||
@ -171,13 +170,16 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean mClosed;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLength,
|
public void renderWay(byte layer, Tag[] tags, float[] coords, short[] indices,
|
||||||
boolean closed) {
|
boolean closed) {
|
||||||
|
|
||||||
mTagName = null;
|
mTagName = null;
|
||||||
mProjected = false;
|
mProjected = false;
|
||||||
mCurLineLayer = null;
|
mCurLineLayer = null;
|
||||||
|
mClosed = closed;
|
||||||
|
|
||||||
mDrawingLayer = getValidLayer(layer) * mLevels;
|
mDrawingLayer = getValidLayer(layer) * mLevels;
|
||||||
mSimplify = 0.5f;
|
mSimplify = 0.5f;
|
||||||
@ -192,8 +194,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
mSimplify = 0;
|
mSimplify = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mWayNodes = wayNodes;
|
mCoords = coords;
|
||||||
mWays = wayLength;
|
mIndices = indices;
|
||||||
|
|
||||||
// remove tags that should not be cached in Rendertheme
|
// remove tags that should not be cached in Rendertheme
|
||||||
filterTags(tags);
|
filterTags(tags);
|
||||||
@ -236,7 +238,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
|
|
||||||
if (caption.textKey == mTagEmptyName.key) {
|
if (caption.textKey == mTagEmptyName.key) {
|
||||||
|
|
||||||
TextItem t = new TextItem(mWayNodes[0], mWayNodes[1], mTagName.value, caption);
|
TextItem t = new TextItem(mCoords[0], mCoords[1], mTagName.value, caption);
|
||||||
t.next = mLabels;
|
t.next = mLabels;
|
||||||
mLabels = t;
|
mLabels = t;
|
||||||
}
|
}
|
||||||
@ -266,8 +268,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
|
|
||||||
if (pathText.textKey == mTagEmptyName.key) {
|
if (pathText.textKey == mTagEmptyName.key) {
|
||||||
|
|
||||||
mLabels = WayDecorator.renderText(mWayNodes, mTagName.value, pathText, 0,
|
mLabels = WayDecorator.renderText(mCoords, mTagName.value, pathText, 0,
|
||||||
mWays[0], mLabels);
|
mIndices[0], mLabels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,6 +337,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
// lineLayer = LineLayers.get(numLayer, line, w, false);
|
// lineLayer = LineLayers.get(numLayer, line, w, false);
|
||||||
lineLayer.next = l.next;
|
lineLayer.next = l.next;
|
||||||
l.next = lineLayer;
|
l.next = lineLayer;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
l = l.next;
|
l = l.next;
|
||||||
}
|
}
|
||||||
@ -351,7 +354,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
|
|
||||||
mCurLineLayer = lineLayer;
|
mCurLineLayer = lineLayer;
|
||||||
|
|
||||||
lineLayer.addLine(mWayNodes, mWays);
|
lineLayer.addLine(mCoords, mIndices, mClosed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -387,6 +390,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
layer = new PolygonLayer(numLayer, area);
|
layer = new PolygonLayer(numLayer, area);
|
||||||
layer.next = l.next;
|
layer.next = l.next;
|
||||||
l.next = layer;
|
l.next = layer;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
l = l.next;
|
l = l.next;
|
||||||
}
|
}
|
||||||
@ -396,7 +400,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
|
|
||||||
mCurPolyLayer = layer;
|
mCurPolyLayer = layer;
|
||||||
|
|
||||||
layer.addPolygon(mWayNodes, mWays);
|
layer.addPolygon(mCoords, mIndices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -405,7 +409,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
@ -414,7 +417,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
private boolean mDebugDrawPolygons;
|
private boolean mDebugDrawPolygons;
|
||||||
boolean mDebugDrawUnmatched;
|
boolean mDebugDrawUnmatched;
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean executeJob(JobTile jobTile) {
|
public boolean executeJob(JobTile jobTile) {
|
||||||
MapTile tile;
|
MapTile tile;
|
||||||
|
|
||||||
@ -455,8 +457,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
|
|
||||||
if (mMapDatabase.executeQuery(tile, this) != QueryResult.SUCCESS) {
|
if (mMapDatabase.executeQuery(tile, this) != QueryResult.SUCCESS) {
|
||||||
Log.d(TAG, "Failed loading: " + tile);
|
Log.d(TAG, "Failed loading: " + tile);
|
||||||
LineLayers.clear(mLineLayers);
|
LineRenderer.clear(mLineLayers);
|
||||||
PolygonLayers.clear(mPolyLayers);
|
PolygonRenderer.clear(mPolyLayers);
|
||||||
mLineLayers = null;
|
mLineLayers = null;
|
||||||
mPolyLayers = null;
|
mPolyLayers = null;
|
||||||
mLabels = null;
|
mLabels = null;
|
||||||
@ -471,8 +473,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
mPoiY = 10;
|
mPoiY = 10;
|
||||||
MapGenerator.renderTheme.matchNode(this, debugTagWay, (byte) 0);
|
MapGenerator.renderTheme.matchNode(this, debugTagWay, (byte) 0);
|
||||||
|
|
||||||
mWays = debugBoxIndex;
|
mIndices = debugBoxIndex;
|
||||||
mWayNodes = debugBoxCoords;
|
mCoords = debugBoxCoords;
|
||||||
mDrawingLayer = 10 * mLevels;
|
mDrawingLayer = 10 * mLevels;
|
||||||
MapGenerator.renderTheme.matchWay(this, debugTagBox, (byte) 0, false, true);
|
MapGenerator.renderTheme.matchWay(this, debugTagBox, (byte) 0, false, true);
|
||||||
}
|
}
|
||||||
@ -518,18 +520,15 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
|
|
||||||
private String mMapProjection;
|
private String mMapProjection;
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMapDatabase(IMapDatabase mapDatabase) {
|
public void setMapDatabase(IMapDatabase mapDatabase) {
|
||||||
mMapDatabase = mapDatabase;
|
mMapDatabase = mapDatabase;
|
||||||
mMapProjection = mMapDatabase.getMapProjection();
|
mMapProjection = mMapDatabase.getMapProjection();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public IMapDatabase getMapDatabase() {
|
public IMapDatabase getMapDatabase() {
|
||||||
return mMapDatabase;
|
return mMapDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRenderTheme(RenderTheme theme) {
|
public void setRenderTheme(RenderTheme theme) {
|
||||||
MapGenerator.renderTheme = theme;
|
MapGenerator.renderTheme = theme;
|
||||||
}
|
}
|
||||||
@ -552,7 +551,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
if (mMapProjection == WebMercator.NAME)
|
if (mMapProjection == WebMercator.NAME)
|
||||||
useWebMercator = true;
|
useWebMercator = true;
|
||||||
|
|
||||||
float[] coords = mWayNodes;
|
float[] coords = mCoords;
|
||||||
|
|
||||||
long x = mCurrentTile.pixelX;
|
long x = mCurrentTile.pixelX;
|
||||||
long y = mCurrentTile.pixelY + Tile.TILE_SIZE;
|
long y = mCurrentTile.pixelY + Tile.TILE_SIZE;
|
||||||
@ -571,8 +570,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
divy = z / PIx4;
|
divy = z / PIx4;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int pos = 0, outPos = 0, i = 0, m = mWays.length; i < m; i++) {
|
for (int pos = 0, outPos = 0, i = 0, m = mIndices.length; i < m; i++) {
|
||||||
int len = mWays[i];
|
int len = mIndices[i];
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
continue;
|
continue;
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
@ -608,7 +607,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
|
|||||||
cnt += 2;
|
cnt += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
mWays[i] = (short) cnt;
|
mIndices[i] = (short) cnt;
|
||||||
}
|
}
|
||||||
mProjected = true;
|
mProjected = true;
|
||||||
// mProjectedResult = true;
|
// mProjectedResult = true;
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -20,22 +20,45 @@ import java.util.Collections;
|
|||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.core.MercatorProjection;
|
import org.oscim.core.MercatorProjection;
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.theme.RenderTheme;
|
||||||
|
import org.oscim.utils.GlConfigChooser;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
import org.oscim.view.glrenderer.MapRenderer.TilesData;
|
import org.oscim.view.generator.JobTile;
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
import org.oscim.view.renderer.GLRenderer.TilesData;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.opengl.GLSurfaceView;
|
||||||
import android.util.FloatMath;
|
import android.util.FloatMath;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
// for lack of a better name... maybe TileManager?
|
public class MapRenderer extends GLSurfaceView {
|
||||||
|
private final static String TAG = "MapRenderer";
|
||||||
|
|
||||||
/**
|
public MapRenderer(Context context, MapView mapView) {
|
||||||
* Update list of visible tiles and passes them to MapRenderer, when not available tiles are created and added to
|
super(context);
|
||||||
* JobQueue (mapView.addJobs) for loading by MapGenerator class
|
|
||||||
*/
|
|
||||||
|
|
||||||
class TileLoader {
|
mMapView = mapView;
|
||||||
private static final String TAG = "TileLoader";
|
|
||||||
|
Log.d(TAG, "init GLSurfaceLayer");
|
||||||
|
setEGLConfigChooser(new GlConfigChooser());
|
||||||
|
setEGLContextClientVersion(2);
|
||||||
|
|
||||||
|
// setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
|
||||||
|
mRenderer = new GLRenderer(mMapView);
|
||||||
|
setRenderer(mRenderer);
|
||||||
|
//
|
||||||
|
// if (!debugFrameTime)
|
||||||
|
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
|
||||||
|
|
||||||
|
mJobList = new ArrayList<JobTile>();
|
||||||
|
mTiles = new ArrayList<MapTile>();
|
||||||
|
mTilesLoaded = new ArrayList<MapTile>(30);
|
||||||
|
|
||||||
|
ShortPool.init();
|
||||||
|
QuadTree.init();
|
||||||
|
|
||||||
|
mInitial = true;
|
||||||
|
}
|
||||||
|
|
||||||
private static final int MAX_TILES_IN_QUEUE = 40;
|
private static final int MAX_TILES_IN_QUEUE = 40;
|
||||||
|
|
||||||
@ -58,28 +81,25 @@ class TileLoader {
|
|||||||
private static boolean mInitial;
|
private static boolean mInitial;
|
||||||
|
|
||||||
// private static MapPosition mCurPosition, mDrawPosition;
|
// private static MapPosition mCurPosition, mDrawPosition;
|
||||||
private static int mWidth, mHeight;
|
private static int mWidth = 0, mHeight = 0;
|
||||||
|
|
||||||
private static TilesData newTiles;
|
private static TilesData newTiles;
|
||||||
|
|
||||||
static void init(MapView mapView, int w, int h, int numTiles) {
|
/**
|
||||||
mMapView = mapView;
|
* called by MapView when position or map settings changes
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Update list of visible tiles and passes them to MapRenderer, when not available tiles are created and added to
|
||||||
|
* JobQueue (mapView.addJobs) for loading by MapGenerator class
|
||||||
|
*
|
||||||
|
* @param clear
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
|
||||||
ShortPool.init();
|
public synchronized void updateMap(boolean clear) {
|
||||||
QuadTree.init();
|
|
||||||
|
|
||||||
mJobList = new ArrayList<JobTile>();
|
if (mWidth == 0 || mHeight == 0)
|
||||||
mTiles = new ArrayList<MapTile>();
|
return;
|
||||||
mTilesLoaded = new ArrayList<MapTile>(30);
|
|
||||||
|
|
||||||
mInitial = true;
|
|
||||||
mWidth = w;
|
|
||||||
mHeight = h;
|
|
||||||
|
|
||||||
newTiles = new TilesData(numTiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
static synchronized void updateMap(boolean clear) {
|
|
||||||
|
|
||||||
boolean changedPos = false;
|
boolean changedPos = false;
|
||||||
boolean changedZoom = false;
|
boolean changedZoom = false;
|
||||||
@ -95,8 +115,10 @@ class TileLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (clear) {
|
if (clear) {
|
||||||
|
Log.d(TAG, "CLEAR");
|
||||||
|
|
||||||
mInitial = true;
|
mInitial = true;
|
||||||
synchronized (MapRenderer.lock) {
|
synchronized (GLRenderer.lock) {
|
||||||
|
|
||||||
for (MapTile t : mTiles)
|
for (MapTile t : mTiles)
|
||||||
clearTile(t);
|
clearTile(t);
|
||||||
@ -107,6 +129,15 @@ class TileLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mInitial) {
|
||||||
|
mRenderer.clearTiles();
|
||||||
|
|
||||||
|
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
|
||||||
|
* (mHeight / (Tile.TILE_SIZE / 2) + 2);
|
||||||
|
Log.d(TAG, "newTiles: " + numTiles);
|
||||||
|
newTiles = new TilesData(numTiles);
|
||||||
|
}
|
||||||
|
|
||||||
byte zoomLevel = mapPosition.zoomLevel;
|
byte zoomLevel = mapPosition.zoomLevel;
|
||||||
float scale = mapPosition.scale;
|
float scale = mapPosition.scale;
|
||||||
|
|
||||||
@ -148,17 +179,17 @@ class TileLoader {
|
|||||||
updateVisibleList(mapPosition, 0);
|
updateVisibleList(mapPosition, 0);
|
||||||
} else {
|
} else {
|
||||||
// pass new position to glThread
|
// pass new position to glThread
|
||||||
MapRenderer.updatePosition(mapPosition);
|
GLRenderer.updatePosition(mapPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MapView.debugFrameTime)
|
if (!MapView.debugFrameTime)
|
||||||
mMapView.requestRender();
|
requestRender();
|
||||||
|
|
||||||
if (changedPos)
|
if (changedPos)
|
||||||
updateVisibleList(mapPosition, zdir);
|
updateVisibleList(mapPosition, zdir);
|
||||||
|
|
||||||
if (changedPos || changedZoom) {
|
if (changedPos || changedZoom) {
|
||||||
int remove = mTiles.size() - MapRenderer.CACHE_TILES;
|
int remove = mTiles.size() - GLRenderer.CACHE_TILES;
|
||||||
if (remove > 50)
|
if (remove > 50)
|
||||||
limitCache(mapPosition, remove);
|
limitCache(mapPosition, remove);
|
||||||
}
|
}
|
||||||
@ -240,8 +271,9 @@ class TileLoader {
|
|||||||
|
|
||||||
// pass new tile list to glThread
|
// pass new tile list to glThread
|
||||||
newTiles.cnt = tiles;
|
newTiles.cnt = tiles;
|
||||||
newTiles = MapRenderer.updateTiles(mapPosition, newTiles);
|
newTiles = GLRenderer.updateTiles(mapPosition, newTiles);
|
||||||
|
|
||||||
|
// note: this sets isLoading == true for all job tiles
|
||||||
if (mJobList.size() > 0) {
|
if (mJobList.size() > 0) {
|
||||||
updateTileDistances(mJobList, mapPosition);
|
updateTileDistances(mJobList, mapPosition);
|
||||||
Collections.sort(mJobList);
|
Collections.sort(mJobList);
|
||||||
@ -252,88 +284,31 @@ class TileLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void clearTile(MapTile t) {
|
private static void clearTile(MapTile t) {
|
||||||
|
|
||||||
t.newData = false;
|
t.newData = false;
|
||||||
t.isLoading = false;
|
t.isLoading = false;
|
||||||
t.isReady = false;
|
t.isReady = false;
|
||||||
|
|
||||||
LineLayers.clear(t.lineLayers);
|
LineRenderer.clear(t.lineLayers);
|
||||||
PolygonLayers.clear(t.polygonLayers);
|
PolygonRenderer.clear(t.polygonLayers);
|
||||||
|
|
||||||
t.labels = null;
|
t.labels = null;
|
||||||
t.lineLayers = null;
|
t.lineLayers = null;
|
||||||
t.polygonLayers = null;
|
t.polygonLayers = null;
|
||||||
|
|
||||||
if (t.vbo != null) {
|
if (t.vbo != null) {
|
||||||
MapRenderer.addVBO(t.vbo);
|
GLRenderer.addVBO(t.vbo);
|
||||||
t.vbo = null;
|
t.vbo = null;
|
||||||
}
|
}
|
||||||
|
if (t.texture != null)
|
||||||
|
t.texture.tile = null;
|
||||||
|
|
||||||
QuadTree.remove(t);
|
QuadTree.remove(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean childIsActive(MapTile t) {
|
// private static boolean tileInUse(MapTile t) {
|
||||||
MapTile c = null;
|
// return (t.isActive || t.refs != 0);
|
||||||
|
// }
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
if (t.rel.child[i] == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
c = t.rel.child[i].tile;
|
|
||||||
if (c != null && c.isActive && !(c.isReady || c.newData))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME still the chance that one jumped two zoomlevels between
|
|
||||||
// cur and draw. should use reference counter instead
|
|
||||||
private static boolean tileInUse(MapTile t) {
|
|
||||||
byte z = mPrevZoom;
|
|
||||||
|
|
||||||
if (t.isActive) {
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if (t.zoomLevel == z + 1) {
|
|
||||||
MapTile p = t.rel.parent.tile;
|
|
||||||
|
|
||||||
if (p != null && p.isActive && !(p.isReady || p.newData))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if (t.zoomLevel == z + 2) {
|
|
||||||
MapTile p = t.rel.parent.parent.tile;
|
|
||||||
|
|
||||||
if (p != null && p.isActive && !(p.isReady || p.newData))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if (t.zoomLevel == z - 1) {
|
|
||||||
if (childIsActive(t))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if (t.zoomLevel == z - 2) {
|
|
||||||
for (QuadTree c : t.rel.child) {
|
|
||||||
if (c == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (c.tile != null && childIsActive(c.tile))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (t.zoomLevel == z - 3) {
|
|
||||||
for (QuadTree c : t.rel.child) {
|
|
||||||
if (c == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (QuadTree c2 : c.child) {
|
|
||||||
if (c2 == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (c2.tile != null && childIsActive(c2.tile))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void updateTileDistances(ArrayList<?> tiles,
|
private static void updateTileDistances(ArrayList<?> tiles,
|
||||||
MapPosition mapPosition) {
|
MapPosition mapPosition) {
|
||||||
@ -386,14 +361,12 @@ class TileLoader {
|
|||||||
int removes = remove;
|
int removes = remove;
|
||||||
|
|
||||||
int size = mTiles.size();
|
int size = mTiles.size();
|
||||||
// int tmp = size;
|
|
||||||
|
|
||||||
// remove orphaned tiles
|
// remove orphaned tiles
|
||||||
for (int i = 0; i < size;) {
|
for (int i = 0; i < size;) {
|
||||||
MapTile cur = mTiles.get(i);
|
MapTile cur = mTiles.get(i);
|
||||||
// make sure tile cannot be used by GL or MapWorker Thread
|
// make sure tile cannot be used by GL or MapWorker Thread
|
||||||
if ((!cur.isActive) && (!cur.isLoading) && (!cur.newData)
|
if (!cur.isLocked() && !cur.isLoading && !cur.newData && !cur.isReady) {
|
||||||
&& (!cur.isReady) && (!tileInUse(cur))) {
|
|
||||||
|
|
||||||
clearTile(cur);
|
clearTile(cur);
|
||||||
mTiles.remove(i);
|
mTiles.remove(i);
|
||||||
@ -405,7 +378,7 @@ class TileLoader {
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log.d(TAG, "remove tiles: " + removes + " " + size + " " + tmp);
|
// Log.d(TAG, "remove tiles: " + removes + " " + size);
|
||||||
|
|
||||||
if (removes <= 0)
|
if (removes <= 0)
|
||||||
return;
|
return;
|
||||||
@ -413,35 +386,25 @@ class TileLoader {
|
|||||||
updateTileDistances(mTiles, mapPosition);
|
updateTileDistances(mTiles, mapPosition);
|
||||||
Collections.sort(mTiles);
|
Collections.sort(mTiles);
|
||||||
|
|
||||||
// boolean printAll = false;
|
|
||||||
|
|
||||||
for (int i = 1; i <= removes; i++) {
|
for (int i = 1; i <= removes; i++) {
|
||||||
|
|
||||||
MapTile t = mTiles.remove(size - i);
|
MapTile t = mTiles.remove(size - i);
|
||||||
|
|
||||||
synchronized (t) {
|
synchronized (t) {
|
||||||
if (t.isActive) {
|
if (t.isLocked()) {
|
||||||
// dont remove tile used by renderthread
|
// dont remove tile used by renderthread
|
||||||
Log.d(TAG, "X not removing active " + t + " " + t.distance);
|
Log.d(TAG, "X not removing " + t + " " + t.isActive + " "
|
||||||
|
+ t.distance);
|
||||||
|
|
||||||
// if (printAll) {
|
|
||||||
// printAll = false;
|
|
||||||
// for (GLMapTile tt : mTiles)
|
|
||||||
// Log.d(TAG, ">>>" + tt + " " + tt.distance);
|
|
||||||
// }
|
|
||||||
mTiles.add(t);
|
|
||||||
} else if ((t.isReady || t.newData) && tileInUse(t)) {
|
|
||||||
// check if this tile could be used as proxy
|
|
||||||
Log.d(TAG, "X not removing proxy: " + t + " " + t.distance);
|
|
||||||
mTiles.add(t);
|
mTiles.add(t);
|
||||||
|
|
||||||
} else if (t.isLoading) {
|
} else if (t.isLoading) {
|
||||||
// FIXME !!! if we add tile back on next limit cache
|
// FIXME if we add tile back on next limit cache
|
||||||
// this will be removed. clearTile could interfere with
|
// this will be removed. clearTile could interfere with
|
||||||
// MapGenerator... clear in passTile().
|
// MapGenerator... clear in passTile().
|
||||||
Log.d(TAG, "X cancel loading " + t + " " + t.distance);
|
Log.d(TAG, "X cancel loading " + t + " " + t.distance);
|
||||||
t.isLoading = false;
|
t.isLoading = false;
|
||||||
// mTiles.add(t);
|
// mTiles.add(t);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
clearTile(t);
|
clearTile(t);
|
||||||
}
|
}
|
||||||
@ -469,12 +432,13 @@ class TileLoader {
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear loaded but not used tiles
|
|
||||||
if (size < MAX_TILES_IN_QUEUE)
|
if (size < MAX_TILES_IN_QUEUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Log.d(TAG, "queue: " + mTilesLoaded.size() + " " + size + " "
|
// Log.d(TAG, "queue: " + mTilesLoaded.size() + " " + size + " "
|
||||||
// + (size - MAX_TILES_IN_QUEUE / 2));
|
// + (size - MAX_TILES_IN_QUEUE / 2));
|
||||||
|
|
||||||
|
// clear loaded but not used tiles
|
||||||
for (int i = 0, n = size - MAX_TILES_IN_QUEUE / 2; i < n; n--) {
|
for (int i = 0, n = size - MAX_TILES_IN_QUEUE / 2; i < n; n--) {
|
||||||
|
|
||||||
MapTile t = mTilesLoaded.get(i);
|
MapTile t = mTilesLoaded.get(i);
|
||||||
@ -485,7 +449,7 @@ class TileLoader {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tileInUse(t)) {
|
if (t.isLocked()) {
|
||||||
// Log.d(TAG, "keep unused tile data: " + t + " " + t.isActive);
|
// Log.d(TAG, "keep unused tile data: " + t + " " + t.isActive);
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
@ -501,14 +465,70 @@ class TileLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage tiles that have data to be uploaded to gl
|
* called from MapWorker Thread when tile is loaded by MapGenerator
|
||||||
*
|
*
|
||||||
* @param tile
|
* @param jobTile
|
||||||
* tile processed by MapGenerator
|
* ...
|
||||||
|
* @return ...
|
||||||
*/
|
*/
|
||||||
static void addTileLoaded(MapTile tile) {
|
public synchronized boolean passTile(JobTile jobTile) {
|
||||||
|
MapTile tile = (MapTile) jobTile;
|
||||||
|
|
||||||
|
if (!tile.isLoading) {
|
||||||
|
// no one should be able to use this tile now, mapgenerator passed it,
|
||||||
|
// glthread does nothing until newdata is set.
|
||||||
|
Log.d(TAG, "passTile: canceled " + tile);
|
||||||
|
synchronized (mTilesLoaded) {
|
||||||
|
mTilesLoaded.add(tile);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mRenderer.setVBO(tile);
|
||||||
|
|
||||||
|
if (tile.vbo == null) {
|
||||||
|
Log.d(TAG, "no VBOs left for " + tile);
|
||||||
|
tile.isLoading = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tile.newData = true;
|
||||||
|
tile.isLoading = false;
|
||||||
|
|
||||||
|
if (!MapView.debugFrameTime)
|
||||||
|
requestRender();
|
||||||
|
|
||||||
synchronized (mTilesLoaded) {
|
synchronized (mTilesLoaded) {
|
||||||
mTilesLoaded.add(tile);
|
mTilesLoaded.add(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRenderTheme(RenderTheme t) {
|
||||||
|
if (mRenderer != null)
|
||||||
|
mRenderer.setRenderTheme(t);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private GLRenderer mRenderer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
|
|
||||||
|
Log.d(TAG, "onSizeChanged" + w + " " + h);
|
||||||
|
mWidth = w;
|
||||||
|
mHeight = h;
|
||||||
|
|
||||||
|
if (mWidth > 0 && mHeight > 0)
|
||||||
|
mInitial = true;
|
||||||
|
|
||||||
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
148
src/org/oscim/view/renderer/MapTile.java
Normal file
148
src/org/oscim/view/renderer/MapTile.java
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* 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 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 License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
|
import org.oscim.view.generator.JobTile;
|
||||||
|
|
||||||
|
class MapTile extends JobTile {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VBO layout: - 16 bytes fill coordinates, n bytes polygon vertices, m bytes lines vertices
|
||||||
|
*/
|
||||||
|
VertexBufferObject vbo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* polygonOffset in vbo is always 16 bytes,
|
||||||
|
*/
|
||||||
|
int lineOffset;
|
||||||
|
|
||||||
|
TextTexture texture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tile data set by MapGenerator:
|
||||||
|
*/
|
||||||
|
LineLayer lineLayers;
|
||||||
|
PolygonLayer polygonLayers;
|
||||||
|
TextItem labels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tile is used by render thread. set by updateVisibleList (main thread).
|
||||||
|
*/
|
||||||
|
boolean isActive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tile has new data to upload to gl
|
||||||
|
*/
|
||||||
|
boolean newData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tile is loaded and ready for drawing.
|
||||||
|
*/
|
||||||
|
boolean isReady;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tile is in view region.
|
||||||
|
*/
|
||||||
|
boolean isVisible;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pointer to access relatives in TileTree
|
||||||
|
*/
|
||||||
|
QuadTree rel;
|
||||||
|
|
||||||
|
byte lastDraw = 0;
|
||||||
|
|
||||||
|
// keep track which tiles are locked as proxy for this tile
|
||||||
|
// 16: parent
|
||||||
|
// 32: grandparent
|
||||||
|
// 1-8: children
|
||||||
|
byte proxies;
|
||||||
|
|
||||||
|
// counting the tiles that use this tile as proxy
|
||||||
|
byte refs;
|
||||||
|
|
||||||
|
boolean isLocked() {
|
||||||
|
return isActive || refs > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void unref() {
|
||||||
|
// if (refs == 0) {
|
||||||
|
// Log.d("MapTile", "XXX already unrefd " + this);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// refs--;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// void ref() {
|
||||||
|
// refs++;
|
||||||
|
// }
|
||||||
|
|
||||||
|
void lock() {
|
||||||
|
|
||||||
|
isActive = true;
|
||||||
|
|
||||||
|
if (isReady || newData)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MapTile p = rel.parent.tile;
|
||||||
|
|
||||||
|
if (p != null && (p.isReady || p.newData || p.isLoading)) {
|
||||||
|
proxies |= (1 << 4);
|
||||||
|
p.refs++;
|
||||||
|
} else {
|
||||||
|
p = rel.parent.parent.tile;
|
||||||
|
if (p != null && (p.isReady || p.newData || p.isLoading)) {
|
||||||
|
proxies |= (1 << 5);
|
||||||
|
p.refs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
if (rel.child[j] != null) {
|
||||||
|
p = rel.child[j].tile;
|
||||||
|
if (p != null && (p.isReady || p.newData || p.isLoading)) {
|
||||||
|
proxies |= (1 << j);
|
||||||
|
p.refs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock() {
|
||||||
|
isActive = false;
|
||||||
|
|
||||||
|
if (proxies == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((proxies & (1 << 4)) != 0) {
|
||||||
|
MapTile p = rel.parent.tile;
|
||||||
|
p.refs--;
|
||||||
|
} else if ((proxies & (1 << 5)) != 0) {
|
||||||
|
MapTile p = rel.parent.parent.tile;
|
||||||
|
p.refs--;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if ((proxies & (1 << i)) != 0) {
|
||||||
|
rel.child[i].tile.refs--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proxies = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MapTile(int tileX, int tileY, byte zoomLevel) {
|
||||||
|
super(tileX, tileY, zoomLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -12,13 +12,13 @@
|
|||||||
* You should have received a copy of the GNU Lesser General License along with
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.theme.renderinstruction.Area;
|
import org.oscim.theme.renderinstruction.Area;
|
||||||
|
|
||||||
class PolygonLayer {
|
class PolygonLayer {
|
||||||
private static final float S = MapRenderer.COORD_MULTIPLIER;
|
private static final float S = GLRenderer.COORD_MULTIPLIER;
|
||||||
|
|
||||||
PolygonLayer next;
|
PolygonLayer next;
|
||||||
Area area;
|
Area area;
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General License along with
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
import static android.opengl.GLES20.GL_BLEND;
|
import static android.opengl.GLES20.GL_BLEND;
|
||||||
import static android.opengl.GLES20.GL_EQUAL;
|
import static android.opengl.GLES20.GL_EQUAL;
|
||||||
@ -30,7 +30,6 @@ import static android.opengl.GLES20.glGetUniformLocation;
|
|||||||
import static android.opengl.GLES20.glStencilFunc;
|
import static android.opengl.GLES20.glStencilFunc;
|
||||||
import static android.opengl.GLES20.glStencilMask;
|
import static android.opengl.GLES20.glStencilMask;
|
||||||
import static android.opengl.GLES20.glStencilOp;
|
import static android.opengl.GLES20.glStencilOp;
|
||||||
import static android.opengl.GLES20.glUniform4f;
|
|
||||||
import static android.opengl.GLES20.glUniform4fv;
|
import static android.opengl.GLES20.glUniform4fv;
|
||||||
import static android.opengl.GLES20.glUniformMatrix4fv;
|
import static android.opengl.GLES20.glUniformMatrix4fv;
|
||||||
import static android.opengl.GLES20.glUseProgram;
|
import static android.opengl.GLES20.glUseProgram;
|
||||||
@ -38,11 +37,11 @@ import static android.opengl.GLES20.glVertexAttribPointer;
|
|||||||
|
|
||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
import org.oscim.view.utils.GlUtils;
|
import org.oscim.utils.GlUtils;
|
||||||
|
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
|
|
||||||
class PolygonLayers {
|
class PolygonRenderer {
|
||||||
private static final int NUM_VERTEX_SHORTS = 2;
|
private static final int NUM_VERTEX_SHORTS = 2;
|
||||||
private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0;
|
private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0;
|
||||||
private static int STENCIL_BITS = 8;
|
private static int STENCIL_BITS = 8;
|
||||||
@ -102,11 +101,8 @@ class PolygonLayers {
|
|||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
blend = true;
|
blend = true;
|
||||||
}
|
}
|
||||||
glUniform4f(hPolygonColor,
|
|
||||||
l.area.color[0] * alpha,
|
GlUtils.setColor(hPolygonColor, l.area.color, alpha);
|
||||||
l.area.color[1] * alpha,
|
|
||||||
l.area.color[2] * alpha,
|
|
||||||
alpha);
|
|
||||||
|
|
||||||
} else if (l.area.blend == zoom) {
|
} else if (l.area.blend == zoom) {
|
||||||
// fade in/out
|
// fade in/out
|
||||||
@ -116,10 +112,9 @@ class PolygonLayers {
|
|||||||
else if (alpha < 0)
|
else if (alpha < 0)
|
||||||
alpha = 0;
|
alpha = 0;
|
||||||
|
|
||||||
glUniform4f(hPolygonColor,
|
GlUtils.setBlendColors(hPolygonColor,
|
||||||
l.area.color[0] * (1 - alpha) + l.area.blendColor[0] * alpha,
|
l.area.color, l.area.blendColor, alpha);
|
||||||
l.area.color[1] * (1 - alpha) + l.area.blendColor[1] * alpha,
|
|
||||||
l.area.color[2] * (1 - alpha) + l.area.blendColor[2] * alpha, 1);
|
|
||||||
} else {
|
} else {
|
||||||
// draw solid
|
// draw solid
|
||||||
if (blend) {
|
if (blend) {
|
||||||
@ -132,6 +127,16 @@ class PolygonLayers {
|
|||||||
glUniform4fv(hPolygonColor, 1, l.area.color, 0);
|
glUniform4fv(hPolygonColor, 1, l.area.color, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (alpha < 1) {
|
||||||
|
// if (!blend) {
|
||||||
|
// glEnable(GL_BLEND);
|
||||||
|
// blend = true;
|
||||||
|
// }
|
||||||
|
// } else if (blend) {
|
||||||
|
// glDisable(GL_BLEND);
|
||||||
|
// blend = false;
|
||||||
|
// }
|
||||||
|
|
||||||
// set stencil buffer mask used to draw this layer
|
// set stencil buffer mask used to draw this layer
|
||||||
glStencilFunc(GL_EQUAL, 0xff, 1 << c);
|
glStencilFunc(GL_EQUAL, 0xff, 1 << c);
|
||||||
|
|
||||||
@ -200,6 +205,7 @@ class PolygonLayers {
|
|||||||
|
|
||||||
// stencil op for stencil method polygon drawing
|
// stencil op for stencil method polygon drawing
|
||||||
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
|
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
|
||||||
|
|
||||||
glDisable(GLES20.GL_DEPTH_TEST);
|
glDisable(GLES20.GL_DEPTH_TEST);
|
||||||
}
|
}
|
||||||
mFillPolys[cnt] = l;
|
mFillPolys[cnt] = l;
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@ -42,12 +42,12 @@ class QuadTree {
|
|||||||
root = new QuadTree();
|
root = new QuadTree();
|
||||||
root.parent = root;
|
root.parent = root;
|
||||||
|
|
||||||
QuadTree t;
|
// QuadTree t;
|
||||||
for (int i = 0; i < 200; i++) {
|
// for (int i = 0; i < 200; i++) {
|
||||||
t = new QuadTree();
|
// t = new QuadTree();
|
||||||
t.parent = pool;
|
// t.parent = pool;
|
||||||
pool = t;
|
// pool = t;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean remove(MapTile t) {
|
static boolean remove(MapTile t) {
|
@ -13,7 +13,7 @@
|
|||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
class Shaders {
|
class Shaders {
|
||||||
|
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
public class ShortItem {
|
public class ShortItem {
|
||||||
final short[] vertices;
|
final short[] vertices;
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
public class SymbolLayer {
|
public class SymbolLayer {
|
||||||
|
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
import org.oscim.theme.renderinstruction.Caption;
|
import org.oscim.theme.renderinstruction.Caption;
|
||||||
import org.oscim.theme.renderinstruction.PathText;
|
import org.oscim.theme.renderinstruction.PathText;
|
@ -12,13 +12,13 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
import org.oscim.view.utils.GlUtils;
|
import org.oscim.utils.GlUtils;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
@ -188,6 +188,7 @@ public class TextRenderer {
|
|||||||
tex = mTextures[i];
|
tex = mTextures[i];
|
||||||
if (tex.tile == null)
|
if (tex.tile == null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!tex.tile.isActive)
|
if (!tex.tile.isActive)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -390,7 +391,8 @@ public class TextRenderer {
|
|||||||
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mBitmap,
|
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mBitmap,
|
||||||
mBitmapFormat, mBitmapType);
|
mBitmapFormat, mBitmapType);
|
||||||
|
|
||||||
// GLES20.glFlush();
|
// FIXME shouldnt be needed here, still looking for sometimes corrupted labels..
|
||||||
|
GLES20.glFlush();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
public class TextTexture {
|
public class TextTexture {
|
||||||
|
|
@ -12,8 +12,8 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.swrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
|
public class TextureLayer {
|
||||||
|
|
||||||
enum ShapeType {
|
|
||||||
CIRCLE, WAY;
|
|
||||||
}
|
}
|
@ -13,7 +13,7 @@
|
|||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
class VertexBufferObject {
|
class VertexBufferObject {
|
||||||
int id;
|
int id;
|
@ -12,10 +12,10 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.glrenderer;
|
package org.oscim.view.renderer;
|
||||||
|
|
||||||
import org.oscim.theme.renderinstruction.PathText;
|
import org.oscim.theme.renderinstruction.PathText;
|
||||||
import org.oscim.view.utils.GeometryUtils;
|
import org.oscim.utils.GeometryUtils;
|
||||||
|
|
||||||
import android.util.FloatMath;
|
import android.util.FloatMath;
|
||||||
|
|
@ -1,254 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.Path;
|
|
||||||
import android.graphics.Typeface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A CanvasRasterer uses a Canvas for drawing.
|
|
||||||
*
|
|
||||||
* @see <a href="http://developer.android.com/reference/android/graphics/Canvas.html">Canvas</a>
|
|
||||||
*/
|
|
||||||
class CanvasRasterer {
|
|
||||||
private static final Paint PAINT_BITMAP_FILTER = new Paint(Paint.FILTER_BITMAP_FLAG);
|
|
||||||
private static final Paint PAINT_TILE_COORDINATES = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
||||||
private static final Paint PAINT_TILE_COORDINATES_STROKE = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
||||||
private static final Paint PAINT_TILE_FRAME = new Paint();
|
|
||||||
|
|
||||||
private static final Paint PAINT_MARK = new Paint();
|
|
||||||
static final int COLOR_MARK = Color.argb(30, 0, 255, 0);
|
|
||||||
|
|
||||||
// private static final float[] TILE_FRAME = new float[] { 0, 0, 0, Tile.TILE_SIZE, 0, Tile.TILE_SIZE,
|
|
||||||
// Tile.TILE_SIZE,
|
|
||||||
// Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE, 0 };
|
|
||||||
|
|
||||||
private static void configurePaints() {
|
|
||||||
PAINT_TILE_COORDINATES.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
|
|
||||||
PAINT_TILE_COORDINATES.setTextSize(12);
|
|
||||||
|
|
||||||
PAINT_TILE_COORDINATES_STROKE.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
|
|
||||||
PAINT_TILE_COORDINATES_STROKE.setStyle(Paint.Style.STROKE);
|
|
||||||
PAINT_TILE_COORDINATES_STROKE.setStrokeWidth(1);
|
|
||||||
PAINT_TILE_COORDINATES_STROKE.setTextSize(6);
|
|
||||||
PAINT_TILE_COORDINATES_STROKE.setColor(Color.WHITE);
|
|
||||||
PAINT_MARK.setColor(COLOR_MARK);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Canvas mCanvas;
|
|
||||||
private final Path mPath;
|
|
||||||
private final Matrix mSymbolMatrix;
|
|
||||||
|
|
||||||
private float mScaleFactor;
|
|
||||||
|
|
||||||
CanvasRasterer() {
|
|
||||||
mCanvas = new Canvas();
|
|
||||||
mSymbolMatrix = new Matrix();
|
|
||||||
mPath = new Path();
|
|
||||||
mPath.setFillType(Path.FillType.EVEN_ODD);
|
|
||||||
mScaleFactor = 1;
|
|
||||||
configurePaints();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void drawTileCoordinate(String string, int offsetY) {
|
|
||||||
mCanvas.drawText(string, 20, offsetY, PAINT_TILE_COORDINATES);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawNodes(List<PointTextContainer> pointTextContainers) {
|
|
||||||
|
|
||||||
for (int index = pointTextContainers.size() - 1; index >= 0; --index) {
|
|
||||||
PointTextContainer pointTextContainer = pointTextContainers.get(index);
|
|
||||||
|
|
||||||
if (pointTextContainer.paintBack != null) {
|
|
||||||
|
|
||||||
mCanvas.drawText(pointTextContainer.text, pointTextContainer.x * mScaleFactor, pointTextContainer.y
|
|
||||||
* mScaleFactor, pointTextContainer.paintBack);
|
|
||||||
}
|
|
||||||
|
|
||||||
mCanvas.drawText(pointTextContainer.text, pointTextContainer.x * mScaleFactor, pointTextContainer.y
|
|
||||||
* mScaleFactor, pointTextContainer.paintFront);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawSymbols(List<SymbolContainer> symbolContainers) {
|
|
||||||
for (int index = symbolContainers.size() - 1; index >= 0; --index) {
|
|
||||||
SymbolContainer symbolContainer = symbolContainers.get(index);
|
|
||||||
|
|
||||||
if (symbolContainer.alignCenter) {
|
|
||||||
int pivotX = symbolContainer.symbol.getWidth() >> 1;
|
|
||||||
int pivotY = symbolContainer.symbol.getHeight() >> 1;
|
|
||||||
mSymbolMatrix.setRotate(symbolContainer.rotation, pivotX, pivotY);
|
|
||||||
mSymbolMatrix.postTranslate(symbolContainer.x - pivotX, symbolContainer.y - pivotY);
|
|
||||||
} else {
|
|
||||||
mSymbolMatrix.setRotate(symbolContainer.rotation);
|
|
||||||
mSymbolMatrix.postTranslate(symbolContainer.x, symbolContainer.y);
|
|
||||||
}
|
|
||||||
mSymbolMatrix.postTranslate(mScaleFactor, mScaleFactor);
|
|
||||||
|
|
||||||
// symbolMatrix.postScale(zoomFactor, zoomFactor);
|
|
||||||
mCanvas.drawBitmap(symbolContainer.symbol, mSymbolMatrix, PAINT_BITMAP_FILTER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawTileCoordinates(Tile tile, long time_load, long time_draw, long blub, long blah) {
|
|
||||||
|
|
||||||
drawTileCoordinate(tile.tileX + " / " + tile.tileY + " / " + tile.zoomLevel + " " + mScaleFactor, 20);
|
|
||||||
|
|
||||||
drawTileCoordinate("l:" + time_load, 40);
|
|
||||||
drawTileCoordinate("d:" + time_draw, 60);
|
|
||||||
drawTileCoordinate("+:" + blub, 80);
|
|
||||||
drawTileCoordinate("-:" + blah, 100);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawTileFrame() {
|
|
||||||
float size = (Tile.TILE_SIZE * mScaleFactor);
|
|
||||||
float[] frame = new float[] { 0, 0, 0, size - 1, 0, size - 1, size - 1, size - 1, size - 1, size - 1, size - 1,
|
|
||||||
0 };
|
|
||||||
mCanvas.drawLines(frame, PAINT_TILE_FRAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawWayNames(float[] coords, List<WayTextContainer> wayTextContainers) {
|
|
||||||
|
|
||||||
for (int index = wayTextContainers.size() - 1; index >= 0; --index) {
|
|
||||||
WayTextContainer wayTextContainer = wayTextContainers.get(index);
|
|
||||||
mPath.rewind();
|
|
||||||
|
|
||||||
int first = wayTextContainer.first;
|
|
||||||
int last = wayTextContainer.last;
|
|
||||||
|
|
||||||
// int len = wayTextContainer.wayDataContainer.length[0];
|
|
||||||
// int pos = wayTextContainer.wayDataContainer.position[0];
|
|
||||||
|
|
||||||
// System.arraycopy(floats, pos, coords, 0, len);
|
|
||||||
|
|
||||||
if (coords[first] < coords[last]) {
|
|
||||||
mPath.moveTo(coords[first], coords[first + 1]);
|
|
||||||
|
|
||||||
for (int i = first + 2; i <= last; i += 2) {
|
|
||||||
mPath.lineTo(coords[i], coords[i + 1]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mPath.moveTo(coords[last], coords[last + 1]);
|
|
||||||
|
|
||||||
for (int i = last - 2; i >= first; i -= 2) {
|
|
||||||
mPath.lineTo(coords[i], coords[i + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mCanvas.drawTextOnPath(wayTextContainer.text, mPath, 0, 3, wayTextContainer.paint);
|
|
||||||
|
|
||||||
// if (wayTextContainer.match)
|
|
||||||
// canvas.drawRect(wayTextContainer.x1,
|
|
||||||
// wayTextContainer.top, wayTextContainer.x2,
|
|
||||||
// wayTextContainer.bot, PAINT_MARK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawWays(float[] coords, LayerContainer[] drawWays) {
|
|
||||||
int levels = drawWays[0].mLevelActive.length;
|
|
||||||
|
|
||||||
for (LayerContainer layerContainer : drawWays) {
|
|
||||||
if (!layerContainer.mActive)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (int level = 0; level < levels; level++) {
|
|
||||||
|
|
||||||
if (!layerContainer.mLevelActive[level])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// mPath.rewind();
|
|
||||||
|
|
||||||
LevelContainer levelContainer = layerContainer.mLevels[level];
|
|
||||||
|
|
||||||
for (int way = levelContainer.mShapeContainers.size() - 1; way >= 0; way--) {
|
|
||||||
mPath.rewind();
|
|
||||||
// switch (shapePaintContainer.shapeContainer.getShapeType()) {
|
|
||||||
//
|
|
||||||
// case WAY:
|
|
||||||
WayDataContainer wayDataContainer = (WayDataContainer) levelContainer.mShapeContainers.get(way);
|
|
||||||
// (WayDataContainer) shapePaintContainer.shapeContainer;
|
|
||||||
|
|
||||||
// if (wayDataContainer.closed) {
|
|
||||||
for (int i = 0, n = wayDataContainer.length.length; i < n; i++) {
|
|
||||||
|
|
||||||
int len = wayDataContainer.length[i];
|
|
||||||
int pos = wayDataContainer.position[i];
|
|
||||||
if (len > 2) {
|
|
||||||
mPath.moveTo(coords[pos], coords[pos + 1]);
|
|
||||||
|
|
||||||
for (int j = pos + 2; j < len + pos; j += 2)
|
|
||||||
mPath.lineTo(coords[j], coords[j + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mCanvas.drawPath(mPath, levelContainer.mPaint[0]);
|
|
||||||
if (levelContainer.mPaint[1] != null)
|
|
||||||
mCanvas.drawPath(mPath, levelContainer.mPaint[1]);
|
|
||||||
|
|
||||||
// }else {
|
|
||||||
// for (int i = 0, n = wayDataContainer.length.length; i < n; i++) {
|
|
||||||
// // levelContainer.mPaint[0].setStrokeJoin(Join.ROUND);
|
|
||||||
//
|
|
||||||
// int len = wayDataContainer.length[i];
|
|
||||||
// int pos = wayDataContainer.position[i];
|
|
||||||
// if (len > 2) {
|
|
||||||
// mCanvas.drawPoints(coords, pos, len, levelContainer.mPaint[0]);
|
|
||||||
// if (levelContainer.mPaint[1] != null)
|
|
||||||
// mCanvas.drawPoints(coords, pos, len, levelContainer.mPaint[1]);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// case CIRCLE:
|
|
||||||
// CircleContainer circleContainer =
|
|
||||||
// (CircleContainer) shapePaintContainer.shapeContainer;
|
|
||||||
//
|
|
||||||
// mPath.rewind();
|
|
||||||
//
|
|
||||||
// mPath.addCircle(circleContainer.mX, circleContainer.mY,
|
|
||||||
// circleContainer.mRadius, Path.Direction.CCW);
|
|
||||||
//
|
|
||||||
// mCanvas.drawPath(mPath, shapePaintContainer.paint);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void fill(int color) {
|
|
||||||
mCanvas.drawColor(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCanvasBitmap(Bitmap bitmap, float scale) {
|
|
||||||
mCanvas.setBitmap(bitmap);
|
|
||||||
// add some extra pixels to avoid < 1px blank edges while scaling
|
|
||||||
mCanvas.clipRect(0, 0, Tile.TILE_SIZE * scale + 2, Tile.TILE_SIZE * scale + 2);
|
|
||||||
mScaleFactor = scale;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
|
|
||||||
class CircleContainer implements ShapeContainer {
|
|
||||||
final float mRadius;
|
|
||||||
final float mX;
|
|
||||||
final float mY;
|
|
||||||
|
|
||||||
CircleContainer(float x, float y, float radius) {
|
|
||||||
mX = x;
|
|
||||||
mY = y;
|
|
||||||
mRadius = radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ShapeType getShapeType() {
|
|
||||||
return ShapeType.CIRCLE;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,985 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.Rect;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class process the methods for the Dependency Cache. It's connected with the LabelPlacement class. The main goal
|
|
||||||
* is, to remove double labels and symbols that are already rendered, from the actual tile. Labels and symbols that,
|
|
||||||
* would be rendered on an already drawn Tile, will be deleted too.
|
|
||||||
*/
|
|
||||||
class DependencyCache {
|
|
||||||
/**
|
|
||||||
* The class holds the data for a symbol with dependencies on other tiles.
|
|
||||||
*
|
|
||||||
* @param <Type>
|
|
||||||
* only two types are reasonable. The DependencySymbol or DependencyText class.
|
|
||||||
*/
|
|
||||||
private static class Dependency<Type> {
|
|
||||||
ImmutablePoint point;
|
|
||||||
final Type value;
|
|
||||||
|
|
||||||
Dependency(Type value, ImmutablePoint point) {
|
|
||||||
this.value = value;
|
|
||||||
this.point = point;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class holds all the information off the possible dependencies on a tile.
|
|
||||||
*/
|
|
||||||
private static class DependencyOnTile {
|
|
||||||
boolean drawn;
|
|
||||||
List<Dependency<DependencyText>> labels;
|
|
||||||
List<Dependency<DependencySymbol>> symbols;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize label, symbol and drawn.
|
|
||||||
*/
|
|
||||||
DependencyOnTile() {
|
|
||||||
this.labels = null;
|
|
||||||
this.symbols = null;
|
|
||||||
this.drawn = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param toAdd
|
|
||||||
* a dependency Symbol
|
|
||||||
*/
|
|
||||||
void addSymbol(Dependency<DependencySymbol> toAdd) {
|
|
||||||
if (this.symbols == null) {
|
|
||||||
this.symbols = new ArrayList<Dependency<DependencySymbol>>();
|
|
||||||
}
|
|
||||||
this.symbols.add(toAdd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param toAdd
|
|
||||||
* a Dependency Text
|
|
||||||
*/
|
|
||||||
void addText(Dependency<DependencyText> toAdd) {
|
|
||||||
if (this.labels == null) {
|
|
||||||
this.labels = new ArrayList<Dependency<DependencyText>>();
|
|
||||||
}
|
|
||||||
this.labels.add(toAdd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The class holds the data for a symbol with dependencies on other tiles.
|
|
||||||
*/
|
|
||||||
private static class DependencySymbol {
|
|
||||||
private final List<Tile> tiles;
|
|
||||||
Bitmap symbol;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a symbol dependency element for the dependency cache.
|
|
||||||
*
|
|
||||||
* @param symbol
|
|
||||||
* reference on the dependency symbol.
|
|
||||||
* @param tile
|
|
||||||
* dependency tile.
|
|
||||||
*/
|
|
||||||
DependencySymbol(Bitmap symbol, Tile tile) {
|
|
||||||
this.symbol = symbol;
|
|
||||||
this.tiles = new LinkedList<Tile>();
|
|
||||||
this.tiles.add(tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an additional tile, which has an dependency with this symbol.
|
|
||||||
*
|
|
||||||
* @param tile
|
|
||||||
* additional tile.
|
|
||||||
*/
|
|
||||||
void addTile(Tile tile) {
|
|
||||||
this.tiles.add(tile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The class holds the data for a label with dependencies on other tiles.
|
|
||||||
*/
|
|
||||||
private static class DependencyText {
|
|
||||||
final Rect boundary;
|
|
||||||
final Paint paintBack;
|
|
||||||
final Paint paintFront;
|
|
||||||
final String text;
|
|
||||||
List<Tile> tiles;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a text dependency in the dependency cache.
|
|
||||||
*
|
|
||||||
* @param paintFront
|
|
||||||
* paint element from the front.
|
|
||||||
* @param paintBack
|
|
||||||
* paint element form the background of the text.
|
|
||||||
* @param text
|
|
||||||
* the text of the element.
|
|
||||||
* @param boundary
|
|
||||||
* the fixed boundary with width and height.
|
|
||||||
* @param tile
|
|
||||||
* all tile in where the element has an influence.
|
|
||||||
*/
|
|
||||||
DependencyText(Paint paintFront, Paint paintBack, String text, Rect boundary, Tile tile) {
|
|
||||||
this.paintFront = paintFront;
|
|
||||||
this.paintBack = paintBack;
|
|
||||||
this.text = text;
|
|
||||||
this.tiles = new LinkedList<Tile>();
|
|
||||||
this.tiles.add(tile);
|
|
||||||
this.boundary = boundary;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addTile(Tile tile) {
|
|
||||||
this.tiles.add(tile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private DependencyOnTile currentDependencyOnTile;
|
|
||||||
private Tile currentTile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hash table, that connects the Tiles with their entries in the dependency cache.
|
|
||||||
*/
|
|
||||||
final Map<Tile, DependencyOnTile> dependencyTable;
|
|
||||||
Dependency<DependencyText> depLabel;
|
|
||||||
Rect rect1;
|
|
||||||
Rect rect2;
|
|
||||||
SymbolContainer smb;
|
|
||||||
DependencyOnTile tmp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for this class, that creates a hashtable for the dependencies.
|
|
||||||
*/
|
|
||||||
DependencyCache() {
|
|
||||||
this.dependencyTable = new Hashtable<Tile, DependencyOnTile>(60);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addLabelsFromDependencyOnTile(List<PointTextContainer> labels) {
|
|
||||||
for (int i = 0; i < this.currentDependencyOnTile.labels.size(); i++) {
|
|
||||||
this.depLabel = this.currentDependencyOnTile.labels.get(i);
|
|
||||||
if (this.depLabel.value.paintBack != null) {
|
|
||||||
labels.add(new PointTextContainer(this.depLabel.value.text, this.depLabel.point.pointX,
|
|
||||||
this.depLabel.point.pointY, this.depLabel.value.paintFront, this.depLabel.value.paintBack));
|
|
||||||
} else {
|
|
||||||
labels.add(new PointTextContainer(this.depLabel.value.text, this.depLabel.point.pointX,
|
|
||||||
this.depLabel.point.pointY, this.depLabel.value.paintFront));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addSymbolsFromDependencyOnTile(List<SymbolContainer> symbols) {
|
|
||||||
for (Dependency<DependencySymbol> depSmb : this.currentDependencyOnTile.symbols) {
|
|
||||||
symbols.add(new SymbolContainer(depSmb.value.symbol, depSmb.point.pointX, depSmb.point.pointY));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fills the dependency entry from the tile and the neighbor tiles with the dependency information, that are
|
|
||||||
* necessary for drawing. To do that every label and symbol that will be drawn, will be checked if it produces
|
|
||||||
* dependencies with other tiles.
|
|
||||||
*
|
|
||||||
* @param pTC
|
|
||||||
* list of the labels
|
|
||||||
*/
|
|
||||||
private void fillDependencyLabels(List<PointTextContainer> pTC) {
|
|
||||||
Tile left = new Tile(this.currentTile.tileX - 1, this.currentTile.tileY, this.currentTile.zoomLevel);
|
|
||||||
Tile right = new Tile(this.currentTile.tileX + 1, this.currentTile.tileY, this.currentTile.zoomLevel);
|
|
||||||
Tile up = new Tile(this.currentTile.tileX, this.currentTile.tileY - 1, this.currentTile.zoomLevel);
|
|
||||||
Tile down = new Tile(this.currentTile.tileX, this.currentTile.tileY + 1, this.currentTile.zoomLevel);
|
|
||||||
|
|
||||||
Tile leftup = new Tile(this.currentTile.tileX - 1, this.currentTile.tileY - 1, this.currentTile.zoomLevel);
|
|
||||||
Tile leftdown = new Tile(this.currentTile.tileX - 1, this.currentTile.tileY + 1, this.currentTile.zoomLevel);
|
|
||||||
Tile rightup = new Tile(this.currentTile.tileX + 1, this.currentTile.tileY - 1, this.currentTile.zoomLevel);
|
|
||||||
Tile rightdown = new Tile(this.currentTile.tileX + 1, this.currentTile.tileY + 1, this.currentTile.zoomLevel);
|
|
||||||
|
|
||||||
PointTextContainer label;
|
|
||||||
DependencyOnTile linkedDep;
|
|
||||||
DependencyText toAdd;
|
|
||||||
|
|
||||||
for (int i = 0; i < pTC.size(); i++) {
|
|
||||||
|
|
||||||
label = pTC.get(i);
|
|
||||||
|
|
||||||
toAdd = null;
|
|
||||||
|
|
||||||
// up
|
|
||||||
if ((label.y - label.boundary.height() < 0.0f) && (!this.dependencyTable.get(up).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(up);
|
|
||||||
|
|
||||||
toAdd = new DependencyText(label.paintFront, label.paintBack, label.text, label.boundary,
|
|
||||||
this.currentTile);
|
|
||||||
|
|
||||||
this.currentDependencyOnTile.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(label.x,
|
|
||||||
label.y)));
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(label.x, label.y
|
|
||||||
+ Tile.TILE_SIZE)));
|
|
||||||
|
|
||||||
toAdd.addTile(up);
|
|
||||||
|
|
||||||
if ((label.x < 0.0f) && (!this.dependencyTable.get(leftup).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(leftup);
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x + Tile.TILE_SIZE, label.y + Tile.TILE_SIZE)));
|
|
||||||
|
|
||||||
toAdd.addTile(leftup);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((label.x + label.boundary.width() > Tile.TILE_SIZE) && (!this.dependencyTable.get(rightup).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(rightup);
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x - Tile.TILE_SIZE, label.y + Tile.TILE_SIZE)));
|
|
||||||
|
|
||||||
toAdd.addTile(rightup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// down
|
|
||||||
if ((label.y > Tile.TILE_SIZE) && (!this.dependencyTable.get(down).drawn)) {
|
|
||||||
|
|
||||||
linkedDep = this.dependencyTable.get(down);
|
|
||||||
|
|
||||||
if (toAdd == null) {
|
|
||||||
toAdd = new DependencyText(label.paintFront, label.paintBack, label.text, label.boundary,
|
|
||||||
this.currentTile);
|
|
||||||
|
|
||||||
this.currentDependencyOnTile.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x, label.y)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(label.x, label.y
|
|
||||||
- Tile.TILE_SIZE)));
|
|
||||||
|
|
||||||
toAdd.addTile(down);
|
|
||||||
|
|
||||||
if ((label.x < 0.0f) && (!this.dependencyTable.get(leftdown).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(leftdown);
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x + Tile.TILE_SIZE, label.y - Tile.TILE_SIZE)));
|
|
||||||
|
|
||||||
toAdd.addTile(leftdown);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((label.x + label.boundary.width() > Tile.TILE_SIZE) && (!this.dependencyTable.get(rightdown).drawn)) {
|
|
||||||
|
|
||||||
linkedDep = this.dependencyTable.get(rightdown);
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x - Tile.TILE_SIZE, label.y - Tile.TILE_SIZE)));
|
|
||||||
|
|
||||||
toAdd.addTile(rightdown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// left
|
|
||||||
|
|
||||||
if ((label.x < 0.0f) && (!this.dependencyTable.get(left).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(left);
|
|
||||||
|
|
||||||
if (toAdd == null) {
|
|
||||||
toAdd = new DependencyText(label.paintFront, label.paintBack, label.text, label.boundary,
|
|
||||||
this.currentTile);
|
|
||||||
|
|
||||||
this.currentDependencyOnTile.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x, label.y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(label.x + Tile.TILE_SIZE,
|
|
||||||
label.y)));
|
|
||||||
|
|
||||||
toAdd.addTile(left);
|
|
||||||
}
|
|
||||||
// right
|
|
||||||
if ((label.x + label.boundary.width() > Tile.TILE_SIZE) && (!this.dependencyTable.get(right).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(right);
|
|
||||||
|
|
||||||
if (toAdd == null) {
|
|
||||||
toAdd = new DependencyText(label.paintFront, label.paintBack, label.text, label.boundary,
|
|
||||||
this.currentTile);
|
|
||||||
|
|
||||||
this.currentDependencyOnTile.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x, label.y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(label.x - Tile.TILE_SIZE,
|
|
||||||
label.y)));
|
|
||||||
|
|
||||||
toAdd.addTile(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check symbols
|
|
||||||
|
|
||||||
if ((label.symbol != null) && (toAdd == null)) {
|
|
||||||
|
|
||||||
if ((label.symbol.y <= 0.0f) && (!this.dependencyTable.get(up).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(up);
|
|
||||||
|
|
||||||
toAdd = new DependencyText(label.paintFront, label.paintBack, label.text, label.boundary,
|
|
||||||
this.currentTile);
|
|
||||||
|
|
||||||
this.currentDependencyOnTile.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x, label.y)));
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(label.x, label.y
|
|
||||||
+ Tile.TILE_SIZE)));
|
|
||||||
|
|
||||||
toAdd.addTile(up);
|
|
||||||
|
|
||||||
if ((label.symbol.x < 0.0f) && (!this.dependencyTable.get(leftup).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(leftup);
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(label.x
|
|
||||||
+ Tile.TILE_SIZE, label.y + Tile.TILE_SIZE)));
|
|
||||||
|
|
||||||
toAdd.addTile(leftup);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((label.symbol.x + label.symbol.symbol.getWidth() > Tile.TILE_SIZE)
|
|
||||||
&& (!this.dependencyTable.get(rightup).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(rightup);
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(label.x
|
|
||||||
- Tile.TILE_SIZE, label.y + Tile.TILE_SIZE)));
|
|
||||||
|
|
||||||
toAdd.addTile(rightup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((label.symbol.y + label.symbol.symbol.getHeight() >= Tile.TILE_SIZE)
|
|
||||||
&& (!this.dependencyTable.get(down).drawn)) {
|
|
||||||
|
|
||||||
linkedDep = this.dependencyTable.get(down);
|
|
||||||
|
|
||||||
if (toAdd == null) {
|
|
||||||
toAdd = new DependencyText(label.paintFront, label.paintBack, label.text, label.boundary,
|
|
||||||
this.currentTile);
|
|
||||||
|
|
||||||
this.currentDependencyOnTile.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x, label.y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(label.x, label.y
|
|
||||||
+ Tile.TILE_SIZE)));
|
|
||||||
|
|
||||||
toAdd.addTile(up);
|
|
||||||
|
|
||||||
if ((label.symbol.x < 0.0f) && (!this.dependencyTable.get(leftdown).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(leftdown);
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(label.x
|
|
||||||
+ Tile.TILE_SIZE, label.y - Tile.TILE_SIZE)));
|
|
||||||
|
|
||||||
toAdd.addTile(leftdown);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((label.symbol.x + label.symbol.symbol.getWidth() > Tile.TILE_SIZE)
|
|
||||||
&& (!this.dependencyTable.get(rightdown).drawn)) {
|
|
||||||
|
|
||||||
linkedDep = this.dependencyTable.get(rightdown);
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(label.x
|
|
||||||
- Tile.TILE_SIZE, label.y - Tile.TILE_SIZE)));
|
|
||||||
|
|
||||||
toAdd.addTile(rightdown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((label.symbol.x <= 0.0f) && (!this.dependencyTable.get(left).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(left);
|
|
||||||
|
|
||||||
if (toAdd == null) {
|
|
||||||
toAdd = new DependencyText(label.paintFront, label.paintBack, label.text, label.boundary,
|
|
||||||
this.currentTile);
|
|
||||||
|
|
||||||
this.currentDependencyOnTile.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x, label.y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x - Tile.TILE_SIZE, label.y)));
|
|
||||||
|
|
||||||
toAdd.addTile(left);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((label.symbol.x + label.symbol.symbol.getWidth() >= Tile.TILE_SIZE)
|
|
||||||
&& (!this.dependencyTable.get(right).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(right);
|
|
||||||
|
|
||||||
if (toAdd == null) {
|
|
||||||
toAdd = new DependencyText(label.paintFront, label.paintBack, label.text, label.boundary,
|
|
||||||
this.currentTile);
|
|
||||||
|
|
||||||
this.currentDependencyOnTile.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x, label.y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
linkedDep.addText(new Dependency<DependencyText>(toAdd, new ImmutablePoint(
|
|
||||||
label.x + Tile.TILE_SIZE, label.y)));
|
|
||||||
|
|
||||||
toAdd.addTile(right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fillDependencyOnTile2(List<PointTextContainer> labels, List<SymbolContainer> symbols,
|
|
||||||
List<PointTextContainer> areaLabels) {
|
|
||||||
Tile left = new Tile(this.currentTile.tileX - 1, this.currentTile.tileY, this.currentTile.zoomLevel);
|
|
||||||
Tile right = new Tile(this.currentTile.tileX + 1, this.currentTile.tileY, this.currentTile.zoomLevel);
|
|
||||||
Tile up = new Tile(this.currentTile.tileX, this.currentTile.tileY - 1, this.currentTile.zoomLevel);
|
|
||||||
Tile down = new Tile(this.currentTile.tileX, this.currentTile.tileY + 1, this.currentTile.zoomLevel);
|
|
||||||
|
|
||||||
Tile leftup = new Tile(this.currentTile.tileX - 1, this.currentTile.tileY - 1, this.currentTile.zoomLevel);
|
|
||||||
Tile leftdown = new Tile(this.currentTile.tileX - 1, this.currentTile.tileY + 1, this.currentTile.zoomLevel);
|
|
||||||
Tile rightup = new Tile(this.currentTile.tileX + 1, this.currentTile.tileY - 1, this.currentTile.zoomLevel);
|
|
||||||
Tile rightdown = new Tile(this.currentTile.tileX + 1, this.currentTile.tileY + 1, this.currentTile.zoomLevel);
|
|
||||||
|
|
||||||
if (this.dependencyTable.get(up) == null) {
|
|
||||||
this.dependencyTable.put(up, new DependencyOnTile());
|
|
||||||
}
|
|
||||||
if (this.dependencyTable.get(down) == null) {
|
|
||||||
this.dependencyTable.put(down, new DependencyOnTile());
|
|
||||||
}
|
|
||||||
if (this.dependencyTable.get(left) == null) {
|
|
||||||
this.dependencyTable.put(left, new DependencyOnTile());
|
|
||||||
}
|
|
||||||
if (this.dependencyTable.get(right) == null) {
|
|
||||||
this.dependencyTable.put(right, new DependencyOnTile());
|
|
||||||
}
|
|
||||||
if (this.dependencyTable.get(leftdown) == null) {
|
|
||||||
this.dependencyTable.put(leftdown, new DependencyOnTile());
|
|
||||||
}
|
|
||||||
if (this.dependencyTable.get(rightup) == null) {
|
|
||||||
this.dependencyTable.put(rightup, new DependencyOnTile());
|
|
||||||
}
|
|
||||||
if (this.dependencyTable.get(leftup) == null) {
|
|
||||||
this.dependencyTable.put(leftup, new DependencyOnTile());
|
|
||||||
}
|
|
||||||
if (this.dependencyTable.get(rightdown) == null) {
|
|
||||||
this.dependencyTable.put(rightdown, new DependencyOnTile());
|
|
||||||
}
|
|
||||||
|
|
||||||
fillDependencyLabels(labels);
|
|
||||||
fillDependencyLabels(areaLabels);
|
|
||||||
|
|
||||||
DependencyOnTile linkedDep;
|
|
||||||
DependencySymbol addSmb;
|
|
||||||
|
|
||||||
for (SymbolContainer symbol : symbols) {
|
|
||||||
addSmb = null;
|
|
||||||
|
|
||||||
// up
|
|
||||||
if ((symbol.y < 0.0f) && (!this.dependencyTable.get(up).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(up);
|
|
||||||
|
|
||||||
addSmb = new DependencySymbol(symbol.symbol, this.currentTile);
|
|
||||||
this.currentDependencyOnTile.addSymbol(new Dependency<DependencySymbol>(addSmb, new ImmutablePoint(
|
|
||||||
symbol.x, symbol.y)));
|
|
||||||
|
|
||||||
linkedDep.addSymbol(new Dependency<DependencySymbol>(addSmb, new ImmutablePoint(symbol.x, symbol.y
|
|
||||||
+ Tile.TILE_SIZE)));
|
|
||||||
addSmb.addTile(up);
|
|
||||||
|
|
||||||
if ((symbol.x < 0.0f) && (!this.dependencyTable.get(leftup).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(leftup);
|
|
||||||
|
|
||||||
linkedDep.addSymbol(new Dependency<DependencySymbol>(addSmb, new ImmutablePoint(symbol.x
|
|
||||||
+ Tile.TILE_SIZE, symbol.y + Tile.TILE_SIZE)));
|
|
||||||
addSmb.addTile(leftup);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((symbol.x + symbol.symbol.getWidth() > Tile.TILE_SIZE)
|
|
||||||
&& (!this.dependencyTable.get(rightup).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(rightup);
|
|
||||||
|
|
||||||
linkedDep.addSymbol(new Dependency<DependencySymbol>(addSmb, new ImmutablePoint(symbol.x
|
|
||||||
- Tile.TILE_SIZE, symbol.y + Tile.TILE_SIZE)));
|
|
||||||
addSmb.addTile(rightup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// down
|
|
||||||
if ((symbol.y + symbol.symbol.getHeight() > Tile.TILE_SIZE) && (!this.dependencyTable.get(down).drawn)) {
|
|
||||||
|
|
||||||
linkedDep = this.dependencyTable.get(down);
|
|
||||||
|
|
||||||
if (addSmb == null) {
|
|
||||||
addSmb = new DependencySymbol(symbol.symbol, this.currentTile);
|
|
||||||
this.currentDependencyOnTile.addSymbol(new Dependency<DependencySymbol>(addSmb, new ImmutablePoint(
|
|
||||||
symbol.x, symbol.y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
linkedDep.addSymbol(new Dependency<DependencySymbol>(addSmb, new ImmutablePoint(symbol.x, symbol.y
|
|
||||||
- Tile.TILE_SIZE)));
|
|
||||||
addSmb.addTile(down);
|
|
||||||
|
|
||||||
if ((symbol.x < 0.0f) && (!this.dependencyTable.get(leftdown).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(leftdown);
|
|
||||||
|
|
||||||
linkedDep.addSymbol(new Dependency<DependencySymbol>(addSmb, new ImmutablePoint(symbol.x
|
|
||||||
+ Tile.TILE_SIZE, symbol.y - Tile.TILE_SIZE)));
|
|
||||||
addSmb.addTile(leftdown);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((symbol.x + symbol.symbol.getWidth() > Tile.TILE_SIZE)
|
|
||||||
&& (!this.dependencyTable.get(rightdown).drawn)) {
|
|
||||||
|
|
||||||
linkedDep = this.dependencyTable.get(rightdown);
|
|
||||||
|
|
||||||
linkedDep.addSymbol(new Dependency<DependencySymbol>(addSmb, new ImmutablePoint(symbol.x
|
|
||||||
- Tile.TILE_SIZE, symbol.y - Tile.TILE_SIZE)));
|
|
||||||
addSmb.addTile(rightdown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// left
|
|
||||||
if ((symbol.x < 0.0f) && (!this.dependencyTable.get(left).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(left);
|
|
||||||
|
|
||||||
if (addSmb == null) {
|
|
||||||
addSmb = new DependencySymbol(symbol.symbol, this.currentTile);
|
|
||||||
this.currentDependencyOnTile.addSymbol(new Dependency<DependencySymbol>(addSmb, new ImmutablePoint(
|
|
||||||
symbol.x, symbol.y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
linkedDep.addSymbol(new Dependency<DependencySymbol>(addSmb, new ImmutablePoint(symbol.x
|
|
||||||
+ Tile.TILE_SIZE, symbol.y)));
|
|
||||||
addSmb.addTile(left);
|
|
||||||
}
|
|
||||||
|
|
||||||
// right
|
|
||||||
if ((symbol.x + symbol.symbol.getWidth() > Tile.TILE_SIZE) && (!this.dependencyTable.get(right).drawn)) {
|
|
||||||
linkedDep = this.dependencyTable.get(right);
|
|
||||||
if (addSmb == null) {
|
|
||||||
addSmb = new DependencySymbol(symbol.symbol, this.currentTile);
|
|
||||||
this.currentDependencyOnTile.addSymbol(new Dependency<DependencySymbol>(addSmb, new ImmutablePoint(
|
|
||||||
symbol.x, symbol.y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
linkedDep.addSymbol(new Dependency<DependencySymbol>(addSmb, new ImmutablePoint(symbol.x
|
|
||||||
- Tile.TILE_SIZE, symbol.y)));
|
|
||||||
addSmb.addTile(right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeOverlappingAreaLabelsWithDependencyLabels(List<PointTextContainer> areaLabels) {
|
|
||||||
PointTextContainer pTC;
|
|
||||||
|
|
||||||
for (int i = 0; i < this.currentDependencyOnTile.labels.size(); i++) {
|
|
||||||
this.depLabel = this.currentDependencyOnTile.labels.get(i);
|
|
||||||
this.rect1 = new android.graphics.Rect((int) (this.depLabel.point.pointX),
|
|
||||||
(int) (this.depLabel.point.pointY - this.depLabel.value.boundary.height()),
|
|
||||||
(int) (this.depLabel.point.pointX + this.depLabel.value.boundary.width()),
|
|
||||||
(int) (this.depLabel.point.pointY));
|
|
||||||
|
|
||||||
for (int x = 0; x < areaLabels.size(); x++) {
|
|
||||||
pTC = areaLabels.get(x);
|
|
||||||
|
|
||||||
this.rect2 = new android.graphics.Rect((int) pTC.x, (int) pTC.y - pTC.boundary.height(), (int) pTC.x
|
|
||||||
+ pTC.boundary.width(), (int) pTC.y);
|
|
||||||
|
|
||||||
if (android.graphics.Rect.intersects(this.rect2, this.rect1)) {
|
|
||||||
areaLabels.remove(x);
|
|
||||||
x--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeOverlappingAreaLabelsWithDependencySymbols(List<PointTextContainer> areaLabels) {
|
|
||||||
PointTextContainer label;
|
|
||||||
|
|
||||||
for (Dependency<DependencySymbol> depSmb : this.currentDependencyOnTile.symbols) {
|
|
||||||
|
|
||||||
this.rect1 = new android.graphics.Rect((int) depSmb.point.pointX, (int) depSmb.point.pointY,
|
|
||||||
(int) depSmb.point.pointX + depSmb.value.symbol.getWidth(), (int) depSmb.point.pointY
|
|
||||||
+ depSmb.value.symbol.getHeight());
|
|
||||||
|
|
||||||
for (int x = 0; x < areaLabels.size(); x++) {
|
|
||||||
label = areaLabels.get(x);
|
|
||||||
|
|
||||||
this.rect2 = new android.graphics.Rect((int) (label.x), (int) (label.y - label.boundary.height()),
|
|
||||||
(int) (label.x + label.boundary.width()), (int) (label.y));
|
|
||||||
|
|
||||||
if (android.graphics.Rect.intersects(this.rect2, this.rect1)) {
|
|
||||||
areaLabels.remove(x);
|
|
||||||
x--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeOverlappingLabelsWithDependencyLabels(List<PointTextContainer> labels) {
|
|
||||||
for (int i = 0; i < this.currentDependencyOnTile.labels.size(); i++) {
|
|
||||||
for (int x = 0; x < labels.size(); x++) {
|
|
||||||
if ((labels.get(x).text.equals(this.currentDependencyOnTile.labels.get(i).value.text))
|
|
||||||
&& (labels.get(x).paintFront
|
|
||||||
.equals(this.currentDependencyOnTile.labels.get(i).value.paintFront))
|
|
||||||
&& (labels.get(x).paintBack.equals(this.currentDependencyOnTile.labels.get(i).value.paintBack))) {
|
|
||||||
labels.remove(x);
|
|
||||||
i--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeOverlappingSymbolsWithDepencySymbols(List<SymbolContainer> symbols, int dis) {
|
|
||||||
SymbolContainer sym;
|
|
||||||
Dependency<DependencySymbol> sym2;
|
|
||||||
|
|
||||||
for (int x = 0; x < this.currentDependencyOnTile.symbols.size(); x++) {
|
|
||||||
sym2 = this.currentDependencyOnTile.symbols.get(x);
|
|
||||||
this.rect1 = new android.graphics.Rect((int) sym2.point.pointX - dis, (int) sym2.point.pointY - dis,
|
|
||||||
(int) sym2.point.pointX + sym2.value.symbol.getWidth() + dis, (int) sym2.point.pointY
|
|
||||||
+ sym2.value.symbol.getHeight() + dis);
|
|
||||||
|
|
||||||
for (int y = 0; y < symbols.size(); y++) {
|
|
||||||
|
|
||||||
sym = symbols.get(y);
|
|
||||||
this.rect2 = new android.graphics.Rect((int) sym.x, (int) sym.y, (int) sym.x + sym.symbol.getWidth(),
|
|
||||||
(int) sym.y + sym.symbol.getHeight());
|
|
||||||
|
|
||||||
if (android.graphics.Rect.intersects(this.rect2, this.rect1)) {
|
|
||||||
symbols.remove(y);
|
|
||||||
y--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeOverlappingSymbolsWithDependencyLabels(List<SymbolContainer> symbols) {
|
|
||||||
for (int i = 0; i < this.currentDependencyOnTile.labels.size(); i++) {
|
|
||||||
this.depLabel = this.currentDependencyOnTile.labels.get(i);
|
|
||||||
this.rect1 = new android.graphics.Rect((int) (this.depLabel.point.pointX),
|
|
||||||
(int) (this.depLabel.point.pointY - this.depLabel.value.boundary.height()),
|
|
||||||
(int) (this.depLabel.point.pointX + this.depLabel.value.boundary.width()),
|
|
||||||
(int) (this.depLabel.point.pointY));
|
|
||||||
|
|
||||||
for (int x = 0; x < symbols.size(); x++) {
|
|
||||||
this.smb = symbols.get(x);
|
|
||||||
|
|
||||||
this.rect2 = new android.graphics.Rect((int) this.smb.x, (int) this.smb.y, (int) this.smb.x
|
|
||||||
+ this.smb.symbol.getWidth(), (int) this.smb.y + this.smb.symbol.getHeight());
|
|
||||||
|
|
||||||
if (android.graphics.Rect.intersects(this.rect2, this.rect1)) {
|
|
||||||
symbols.remove(x);
|
|
||||||
x--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method fills the entries in the dependency cache of the tiles, if their dependencies.
|
|
||||||
*
|
|
||||||
* @param labels
|
|
||||||
* current labels, that will be displayed.
|
|
||||||
* @param symbols
|
|
||||||
* current symbols, that will be displayed.
|
|
||||||
* @param areaLabels
|
|
||||||
* current areaLabels, that will be displayed.
|
|
||||||
*/
|
|
||||||
void fillDependencyOnTile(List<PointTextContainer> labels, List<SymbolContainer> symbols,
|
|
||||||
List<PointTextContainer> areaLabels) {
|
|
||||||
this.currentDependencyOnTile.drawn = true;
|
|
||||||
|
|
||||||
if ((!labels.isEmpty()) || (!symbols.isEmpty()) || (!areaLabels.isEmpty())) {
|
|
||||||
fillDependencyOnTile2(labels, symbols, areaLabels);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.currentDependencyOnTile.labels != null) {
|
|
||||||
addLabelsFromDependencyOnTile(labels);
|
|
||||||
}
|
|
||||||
if (this.currentDependencyOnTile.symbols != null) {
|
|
||||||
addSymbolsFromDependencyOnTile(symbols);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method must be called, before the dependencies will be handled correctly. Because it sets the actual Tile
|
|
||||||
* and looks if it has already dependencies.
|
|
||||||
*
|
|
||||||
* @param tile
|
|
||||||
* the current Tile
|
|
||||||
*/
|
|
||||||
void generateTileAndDependencyOnTile(Tile tile) {
|
|
||||||
this.currentTile = new Tile(tile.tileX, tile.tileY, tile.zoomLevel);
|
|
||||||
this.currentDependencyOnTile = this.dependencyTable.get(this.currentTile);
|
|
||||||
|
|
||||||
if (this.currentDependencyOnTile == null) {
|
|
||||||
this.dependencyTable.put(this.currentTile, new DependencyOnTile());
|
|
||||||
this.currentDependencyOnTile = this.dependencyTable.get(this.currentTile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the are labels from the actual list, that would be rendered in a Tile that has already be drawn.
|
|
||||||
*
|
|
||||||
* @param areaLabels
|
|
||||||
* current area Labels, that will be displayed
|
|
||||||
*/
|
|
||||||
void removeAreaLabelsInAlreadyDrawnAreas(List<PointTextContainer> areaLabels) {
|
|
||||||
Tile lefttmp = new Tile(this.currentTile.tileX - 1, this.currentTile.tileY, this.currentTile.zoomLevel);
|
|
||||||
Tile righttmp = new Tile(this.currentTile.tileX + 1, this.currentTile.tileY, this.currentTile.zoomLevel);
|
|
||||||
Tile uptmp = new Tile(this.currentTile.tileX, this.currentTile.tileY - 1, this.currentTile.zoomLevel);
|
|
||||||
Tile downtmp = new Tile(this.currentTile.tileX, this.currentTile.tileY + 1, this.currentTile.zoomLevel);
|
|
||||||
|
|
||||||
boolean up;
|
|
||||||
boolean left;
|
|
||||||
boolean right;
|
|
||||||
boolean down;
|
|
||||||
|
|
||||||
this.tmp = this.dependencyTable.get(lefttmp);
|
|
||||||
left = this.tmp == null ? false : this.tmp.drawn;
|
|
||||||
|
|
||||||
this.tmp = this.dependencyTable.get(righttmp);
|
|
||||||
right = this.tmp == null ? false : this.tmp.drawn;
|
|
||||||
|
|
||||||
this.tmp = this.dependencyTable.get(uptmp);
|
|
||||||
up = this.tmp == null ? false : this.tmp.drawn;
|
|
||||||
|
|
||||||
this.tmp = this.dependencyTable.get(downtmp);
|
|
||||||
down = this.tmp == null ? false : this.tmp.drawn;
|
|
||||||
|
|
||||||
PointTextContainer label;
|
|
||||||
|
|
||||||
for (int i = 0; i < areaLabels.size(); i++) {
|
|
||||||
label = areaLabels.get(i);
|
|
||||||
|
|
||||||
if (up && label.y - label.boundary.height() < 0.0f) {
|
|
||||||
areaLabels.remove(i);
|
|
||||||
i--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (down && label.y > Tile.TILE_SIZE) {
|
|
||||||
areaLabels.remove(i);
|
|
||||||
i--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (left && label.x < 0.0f) {
|
|
||||||
areaLabels.remove(i);
|
|
||||||
i--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (right && label.x + label.boundary.width() > Tile.TILE_SIZE) {
|
|
||||||
areaLabels.remove(i);
|
|
||||||
i--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all objects that overlaps with the objects from the dependency cache.
|
|
||||||
*
|
|
||||||
* @param labels
|
|
||||||
* labels from the current tile
|
|
||||||
* @param areaLabels
|
|
||||||
* area labels from the current tile
|
|
||||||
* @param symbols
|
|
||||||
* symbols from the current tile
|
|
||||||
*/
|
|
||||||
void removeOverlappingObjectsWithDependencyOnTile(List<PointTextContainer> labels,
|
|
||||||
List<PointTextContainer> areaLabels, List<SymbolContainer> symbols) {
|
|
||||||
if (this.currentDependencyOnTile.labels != null && this.currentDependencyOnTile.labels.size() != 0) {
|
|
||||||
removeOverlappingLabelsWithDependencyLabels(labels);
|
|
||||||
removeOverlappingSymbolsWithDependencyLabels(symbols);
|
|
||||||
removeOverlappingAreaLabelsWithDependencyLabels(areaLabels);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.currentDependencyOnTile.symbols != null && this.currentDependencyOnTile.symbols.size() != 0) {
|
|
||||||
removeOverlappingSymbolsWithDepencySymbols(symbols, 2);
|
|
||||||
removeOverlappingAreaLabelsWithDependencySymbols(areaLabels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When the LabelPlacement class generates potential label positions for an POI, there should be no possible
|
|
||||||
* positions, that collide with existing symbols or labels in the dependency Cache. This class implements this
|
|
||||||
* functionality.
|
|
||||||
*
|
|
||||||
* @param refPos
|
|
||||||
* possible label positions form the two or four point Greedy
|
|
||||||
*/
|
|
||||||
void removeReferencePointsFromDependencyCache(LabelPlacement.ReferencePosition[] refPos) {
|
|
||||||
Tile lefttmp = new Tile(this.currentTile.tileX - 1, this.currentTile.tileY, this.currentTile.zoomLevel);
|
|
||||||
Tile righttmp = new Tile(this.currentTile.tileX + 1, this.currentTile.tileY, this.currentTile.zoomLevel);
|
|
||||||
Tile uptmp = new Tile(this.currentTile.tileX, this.currentTile.tileY - 1, this.currentTile.zoomLevel);
|
|
||||||
Tile downtmp = new Tile(this.currentTile.tileX, this.currentTile.tileY + 1, this.currentTile.zoomLevel);
|
|
||||||
|
|
||||||
boolean up;
|
|
||||||
boolean left;
|
|
||||||
boolean right;
|
|
||||||
boolean down;
|
|
||||||
|
|
||||||
this.tmp = this.dependencyTable.get(lefttmp);
|
|
||||||
left = this.tmp == null ? false : this.tmp.drawn;
|
|
||||||
|
|
||||||
this.tmp = this.dependencyTable.get(righttmp);
|
|
||||||
right = this.tmp == null ? false : this.tmp.drawn;
|
|
||||||
|
|
||||||
this.tmp = this.dependencyTable.get(uptmp);
|
|
||||||
up = this.tmp == null ? false : this.tmp.drawn;
|
|
||||||
|
|
||||||
this.tmp = this.dependencyTable.get(downtmp);
|
|
||||||
down = this.tmp == null ? false : this.tmp.drawn;
|
|
||||||
|
|
||||||
LabelPlacement.ReferencePosition ref;
|
|
||||||
|
|
||||||
for (int i = 0; i < refPos.length; i++) {
|
|
||||||
ref = refPos[i];
|
|
||||||
|
|
||||||
if (ref == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (up && ref.y - ref.height < 0) {
|
|
||||||
refPos[i] = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (down && ref.y >= Tile.TILE_SIZE) {
|
|
||||||
refPos[i] = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (left && ref.x < 0) {
|
|
||||||
refPos[i] = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (right && ref.x + ref.width > Tile.TILE_SIZE) {
|
|
||||||
refPos[i] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// removes all Reverence Points that intersects with Labels from the Dependency Cache
|
|
||||||
|
|
||||||
int dis = 2;
|
|
||||||
if (this.currentDependencyOnTile != null) {
|
|
||||||
if (this.currentDependencyOnTile.labels != null) {
|
|
||||||
for (int i = 0; i < this.currentDependencyOnTile.labels.size(); i++) {
|
|
||||||
this.depLabel = this.currentDependencyOnTile.labels.get(i);
|
|
||||||
this.rect1 = new android.graphics.Rect((int) this.depLabel.point.pointX - dis,
|
|
||||||
(int) (this.depLabel.point.pointY - this.depLabel.value.boundary.height()) - dis,
|
|
||||||
(int) (this.depLabel.point.pointX + this.depLabel.value.boundary.width() + dis),
|
|
||||||
(int) (this.depLabel.point.pointY + dis));
|
|
||||||
|
|
||||||
for (int y = 0; y < refPos.length; y++) {
|
|
||||||
if (refPos[y] != null) {
|
|
||||||
this.rect2 = new android.graphics.Rect((int) refPos[y].x,
|
|
||||||
(int) (refPos[y].y - refPos[y].height), (int) (refPos[y].x + refPos[y].width),
|
|
||||||
(int) (refPos[y].y));
|
|
||||||
|
|
||||||
if (android.graphics.Rect.intersects(this.rect2, this.rect1)) {
|
|
||||||
refPos[y] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.currentDependencyOnTile.symbols != null) {
|
|
||||||
for (Dependency<DependencySymbol> symbols2 : this.currentDependencyOnTile.symbols) {
|
|
||||||
|
|
||||||
this.rect1 = new android.graphics.Rect((int) symbols2.point.pointX, (int) (symbols2.point.pointY),
|
|
||||||
(int) (symbols2.point.pointX + symbols2.value.symbol.getWidth()),
|
|
||||||
(int) (symbols2.point.pointY + symbols2.value.symbol.getHeight()));
|
|
||||||
|
|
||||||
for (int y = 0; y < refPos.length; y++) {
|
|
||||||
if (refPos[y] != null) {
|
|
||||||
this.rect2 = new android.graphics.Rect((int) refPos[y].x,
|
|
||||||
(int) (refPos[y].y - refPos[y].height), (int) (refPos[y].x + refPos[y].width),
|
|
||||||
(int) (refPos[y].y));
|
|
||||||
|
|
||||||
if (android.graphics.Rect.intersects(this.rect2, this.rect1)) {
|
|
||||||
refPos[y] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeSymbolsFromDrawnAreas(List<SymbolContainer> symbols) {
|
|
||||||
Tile lefttmp = new Tile(this.currentTile.tileX - 1, this.currentTile.tileY, this.currentTile.zoomLevel);
|
|
||||||
Tile righttmp = new Tile(this.currentTile.tileX + 1, this.currentTile.tileY, this.currentTile.zoomLevel);
|
|
||||||
Tile uptmp = new Tile(this.currentTile.tileX, this.currentTile.tileY - 1, this.currentTile.zoomLevel);
|
|
||||||
Tile downtmp = new Tile(this.currentTile.tileX, this.currentTile.tileY + 1, this.currentTile.zoomLevel);
|
|
||||||
|
|
||||||
boolean up;
|
|
||||||
boolean left;
|
|
||||||
boolean right;
|
|
||||||
boolean down;
|
|
||||||
|
|
||||||
this.tmp = this.dependencyTable.get(lefttmp);
|
|
||||||
left = this.tmp == null ? false : this.tmp.drawn;
|
|
||||||
|
|
||||||
this.tmp = this.dependencyTable.get(righttmp);
|
|
||||||
right = this.tmp == null ? false : this.tmp.drawn;
|
|
||||||
|
|
||||||
this.tmp = this.dependencyTable.get(uptmp);
|
|
||||||
up = this.tmp == null ? false : this.tmp.drawn;
|
|
||||||
|
|
||||||
this.tmp = this.dependencyTable.get(downtmp);
|
|
||||||
down = this.tmp == null ? false : this.tmp.drawn;
|
|
||||||
|
|
||||||
SymbolContainer ref;
|
|
||||||
|
|
||||||
for (int i = 0; i < symbols.size(); i++) {
|
|
||||||
ref = symbols.get(i);
|
|
||||||
|
|
||||||
if (up && ref.y < 0) {
|
|
||||||
symbols.remove(i);
|
|
||||||
i--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (down && ref.y + ref.symbol.getHeight() > Tile.TILE_SIZE) {
|
|
||||||
symbols.remove(i);
|
|
||||||
i--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (left && ref.x < 0) {
|
|
||||||
symbols.remove(i);
|
|
||||||
i--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (right && ref.x + ref.symbol.getWidth() > Tile.TILE_SIZE) {
|
|
||||||
symbols.remove(i);
|
|
||||||
i--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An ImmutablePoint represents an fixed pair of float coordinates.
|
|
||||||
*/
|
|
||||||
class ImmutablePoint implements Comparable<ImmutablePoint> {
|
|
||||||
/**
|
|
||||||
* Subtracts the x and y coordinates of one point from another point.
|
|
||||||
*
|
|
||||||
* @param minuend
|
|
||||||
* the minuend.
|
|
||||||
* @param subtrahend
|
|
||||||
* the subtrahend.
|
|
||||||
* @return a new Point object.
|
|
||||||
*/
|
|
||||||
static ImmutablePoint substract(ImmutablePoint minuend, ImmutablePoint subtrahend) {
|
|
||||||
return new ImmutablePoint(minuend.pointX - subtrahend.pointX, minuend.pointY - subtrahend.pointY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores the hash code of this object.
|
|
||||||
*/
|
|
||||||
private final int hashCodeValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* X coordinate of this point.
|
|
||||||
*/
|
|
||||||
final float pointX;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Y coordinate of this point.
|
|
||||||
*/
|
|
||||||
final float pointY;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param x
|
|
||||||
* the x coordinate of the point.
|
|
||||||
* @param y
|
|
||||||
* the y coordinate of the point.
|
|
||||||
*/
|
|
||||||
ImmutablePoint(float x, float y) {
|
|
||||||
this.pointX = x;
|
|
||||||
this.pointY = y;
|
|
||||||
this.hashCodeValue = calculateHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(ImmutablePoint point) {
|
|
||||||
if (this.pointX > point.pointX) {
|
|
||||||
return 1;
|
|
||||||
} else if (this.pointX < point.pointX) {
|
|
||||||
return -1;
|
|
||||||
} else if (this.pointY > point.pointY) {
|
|
||||||
return 1;
|
|
||||||
} else if (this.pointY < point.pointY) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
} else if (!(obj instanceof ImmutablePoint)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ImmutablePoint other = (ImmutablePoint) obj;
|
|
||||||
if (this.pointX != other.pointX) {
|
|
||||||
return false;
|
|
||||||
} else if (this.pointY != other.pointY) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.hashCodeValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
stringBuilder.append("ImmutablePoint [x=");
|
|
||||||
stringBuilder.append(this.pointX);
|
|
||||||
stringBuilder.append(", y=");
|
|
||||||
stringBuilder.append(this.pointY);
|
|
||||||
stringBuilder.append("]");
|
|
||||||
return stringBuilder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the hash code of this object.
|
|
||||||
*/
|
|
||||||
private int calculateHashCode() {
|
|
||||||
int result = 7;
|
|
||||||
result = 31 * result + Float.floatToIntBits(this.pointX);
|
|
||||||
result = 31 * result + Float.floatToIntBits(this.pointY);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,766 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.PriorityQueue;
|
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
|
||||||
|
|
||||||
import android.graphics.Rect;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class place the labels form POIs, area labels and normal labels. The main target is avoiding collisions of these
|
|
||||||
* different labels.
|
|
||||||
*/
|
|
||||||
class LabelPlacement {
|
|
||||||
/**
|
|
||||||
* This class holds the reference positions for the two and four point greedy algorithms.
|
|
||||||
*/
|
|
||||||
static class ReferencePosition {
|
|
||||||
final float height;
|
|
||||||
final int nodeNumber;
|
|
||||||
SymbolContainer symbol;
|
|
||||||
final float width;
|
|
||||||
final float x;
|
|
||||||
final float y;
|
|
||||||
|
|
||||||
ReferencePosition(float x, float y, int nodeNumber, float width, float height, SymbolContainer symbol) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.nodeNumber = nodeNumber;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.symbol = symbol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class ReferencePositionHeightComparator implements Comparator<ReferencePosition>, Serializable {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
static final ReferencePositionHeightComparator INSTANCE = new ReferencePositionHeightComparator();
|
|
||||||
|
|
||||||
private ReferencePositionHeightComparator() {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(ReferencePosition x, ReferencePosition y) {
|
|
||||||
if (x.y - x.height < y.y - y.height) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x.y - x.height > y.y - y.height) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class ReferencePositionWidthComparator implements Comparator<ReferencePosition>, Serializable {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
static final ReferencePositionWidthComparator INSTANCE = new ReferencePositionWidthComparator();
|
|
||||||
|
|
||||||
private ReferencePositionWidthComparator() {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(ReferencePosition x, ReferencePosition y) {
|
|
||||||
if (x.x + x.width < y.x + y.width) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x.x + x.width > y.x + y.width) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class ReferencePositionXComparator implements Comparator<ReferencePosition>, Serializable {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
static final ReferencePositionXComparator INSTANCE = new ReferencePositionXComparator();
|
|
||||||
|
|
||||||
private ReferencePositionXComparator() {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(ReferencePosition x, ReferencePosition y) {
|
|
||||||
if (x.x < y.x) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x.x > y.x) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class ReferencePositionYComparator implements Comparator<ReferencePosition>, Serializable {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
static final ReferencePositionYComparator INSTANCE = new ReferencePositionYComparator();
|
|
||||||
|
|
||||||
private ReferencePositionYComparator() {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(ReferencePosition x, ReferencePosition y) {
|
|
||||||
if (x.y < y.y) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x.y > y.y) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int PLACEMENT_MODEL = 1;
|
|
||||||
private int mLabelDistanceToLabel = 2;
|
|
||||||
private int mLabelDistanceToSymbol = 2;
|
|
||||||
// You can choose between 2 Position and 4 Position
|
|
||||||
// placement Model 0 - 2-Position 1 - 4 Position
|
|
||||||
// distance adjustments
|
|
||||||
private int mStartDistanceToSymbols = 4;
|
|
||||||
private int mSymbolDistanceToSymbol = 2;
|
|
||||||
|
|
||||||
final DependencyCache mDependencyCache;
|
|
||||||
PointTextContainer mLabel;
|
|
||||||
Rect mRect1;
|
|
||||||
Rect mRect2;
|
|
||||||
ReferencePosition mReferencePosition;
|
|
||||||
SymbolContainer mSymbolContainer;
|
|
||||||
|
|
||||||
LabelPlacement() {
|
|
||||||
mDependencyCache = new DependencyCache();
|
|
||||||
mRect1 = new Rect();
|
|
||||||
mRect2 = new Rect();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Centers the labels.
|
|
||||||
*
|
|
||||||
* @param labels
|
|
||||||
* labels to center
|
|
||||||
*/
|
|
||||||
private void centerLabels(List<PointTextContainer> labels) {
|
|
||||||
for (int i = 0; i < labels.size(); i++) {
|
|
||||||
mLabel = labels.get(i);
|
|
||||||
mLabel.x = mLabel.x - mLabel.boundary.width() / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void preprocessAreaLabels(List<PointTextContainer> areaLabels) {
|
|
||||||
centerLabels(areaLabels);
|
|
||||||
|
|
||||||
removeOutOfTileAreaLabels(areaLabels);
|
|
||||||
|
|
||||||
removeOverlappingAreaLabels(areaLabels);
|
|
||||||
|
|
||||||
if (!areaLabels.isEmpty()) {
|
|
||||||
mDependencyCache.removeAreaLabelsInAlreadyDrawnAreas(areaLabels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void preprocessLabels(List<PointTextContainer> labels) {
|
|
||||||
removeOutOfTileLabels(labels);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void preprocessSymbols(List<SymbolContainer> symbols) {
|
|
||||||
removeOutOfTileSymbols(symbols);
|
|
||||||
removeOverlappingSymbols(symbols);
|
|
||||||
mDependencyCache.removeSymbolsFromDrawnAreas(symbols);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method uses an adapted greedy strategy for the fixed four position model, above, under left and right form
|
|
||||||
* the point of interest. It uses no priority search tree, because it will not function with symbols only with
|
|
||||||
* points. Instead it uses two minimum heaps. They work similar to a sweep line algorithm but have not a O(n log n
|
|
||||||
* +k) runtime. To find the rectangle that has the top edge, I use also a minimum Heap. The rectangles are sorted by
|
|
||||||
* their y coordinates.
|
|
||||||
*
|
|
||||||
* @param labels
|
|
||||||
* label positions and text
|
|
||||||
* @param symbols
|
|
||||||
* symbol positions
|
|
||||||
* @param areaLabels
|
|
||||||
* area label positions and text
|
|
||||||
* @return list of labels without overlaps with symbols and other labels by the four fixed position greedy strategy
|
|
||||||
*/
|
|
||||||
private List<PointTextContainer> processFourPointGreedy(List<PointTextContainer> labels,
|
|
||||||
List<SymbolContainer> symbols, List<PointTextContainer> areaLabels) {
|
|
||||||
List<PointTextContainer> resolutionSet = new ArrayList<PointTextContainer>();
|
|
||||||
|
|
||||||
// Array for the generated reference positions around the points of
|
|
||||||
// interests
|
|
||||||
ReferencePosition[] refPos = new ReferencePosition[(labels.size()) * 4];
|
|
||||||
|
|
||||||
// lists that sorts the reference points after the minimum top edge y
|
|
||||||
// position
|
|
||||||
PriorityQueue<ReferencePosition> priorUp = new PriorityQueue<ReferencePosition>(labels.size() * 4 * 2
|
|
||||||
+ labels.size() / 10 * 2, ReferencePositionYComparator.INSTANCE);
|
|
||||||
// lists that sorts the reference points after the minimum bottom edge y
|
|
||||||
// position
|
|
||||||
PriorityQueue<ReferencePosition> priorDown = new PriorityQueue<ReferencePosition>(labels.size() * 4 * 2
|
|
||||||
+ labels.size() / 10 * 2, ReferencePositionHeightComparator.INSTANCE);
|
|
||||||
|
|
||||||
PointTextContainer tmp;
|
|
||||||
int dis = mStartDistanceToSymbols;
|
|
||||||
|
|
||||||
// creates the reference positions
|
|
||||||
for (int z = 0; z < labels.size(); z++) {
|
|
||||||
if (labels.get(z) != null) {
|
|
||||||
if (labels.get(z).symbol != null) {
|
|
||||||
tmp = labels.get(z);
|
|
||||||
|
|
||||||
// up
|
|
||||||
refPos[z * 4] = new ReferencePosition(tmp.x - tmp.boundary.width() / 2, tmp.y
|
|
||||||
- tmp.symbol.symbol.getHeight() / 2 - dis, z, tmp.boundary.width(), tmp.boundary.height(),
|
|
||||||
tmp.symbol);
|
|
||||||
// down
|
|
||||||
refPos[z * 4 + 1] = new ReferencePosition(tmp.x - tmp.boundary.width() / 2, tmp.y
|
|
||||||
+ tmp.symbol.symbol.getHeight() / 2 + tmp.boundary.height() + dis, z, tmp.boundary.width(),
|
|
||||||
tmp.boundary.height(), tmp.symbol);
|
|
||||||
// left
|
|
||||||
refPos[z * 4 + 2] = new ReferencePosition(tmp.x - tmp.symbol.symbol.getWidth() / 2
|
|
||||||
- tmp.boundary.width() - dis, tmp.y + tmp.boundary.height() / 2, z, tmp.boundary.width(),
|
|
||||||
tmp.boundary.height(), tmp.symbol);
|
|
||||||
// right
|
|
||||||
refPos[z * 4 + 3] = new ReferencePosition(tmp.x + tmp.symbol.symbol.getWidth() / 2 + dis, tmp.y
|
|
||||||
+ tmp.boundary.height() / 2 - 0.1f, z, tmp.boundary.width(), tmp.boundary.height(),
|
|
||||||
tmp.symbol);
|
|
||||||
} else {
|
|
||||||
refPos[z * 4] = new ReferencePosition(labels.get(z).x - ((labels.get(z).boundary.width()) / 2),
|
|
||||||
labels.get(z).y, z, labels.get(z).boundary.width(), labels.get(z).boundary.height(), null);
|
|
||||||
refPos[z * 4 + 1] = null;
|
|
||||||
refPos[z * 4 + 2] = null;
|
|
||||||
refPos[z * 4 + 3] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
removeNonValidateReferencePosition(refPos, symbols, areaLabels);
|
|
||||||
|
|
||||||
// do while it gives reference positions
|
|
||||||
for (int i = 0; i < refPos.length; i++) {
|
|
||||||
mReferencePosition = refPos[i];
|
|
||||||
if (mReferencePosition != null) {
|
|
||||||
priorUp.add(mReferencePosition);
|
|
||||||
priorDown.add(mReferencePosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (priorUp.size() != 0) {
|
|
||||||
mReferencePosition = priorUp.remove();
|
|
||||||
|
|
||||||
mLabel = labels.get(mReferencePosition.nodeNumber);
|
|
||||||
|
|
||||||
resolutionSet.add(new PointTextContainer(mLabel.text, mReferencePosition.x,
|
|
||||||
mReferencePosition.y, mLabel.paintFront, mLabel.paintBack, mLabel.symbol));
|
|
||||||
|
|
||||||
if (priorUp.size() == 0) {
|
|
||||||
return resolutionSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
priorUp.remove(refPos[mReferencePosition.nodeNumber * 4 + 0]);
|
|
||||||
priorUp.remove(refPos[mReferencePosition.nodeNumber * 4 + 1]);
|
|
||||||
priorUp.remove(refPos[mReferencePosition.nodeNumber * 4 + 2]);
|
|
||||||
priorUp.remove(refPos[mReferencePosition.nodeNumber * 4 + 3]);
|
|
||||||
|
|
||||||
priorDown.remove(refPos[mReferencePosition.nodeNumber * 4 + 0]);
|
|
||||||
priorDown.remove(refPos[mReferencePosition.nodeNumber * 4 + 1]);
|
|
||||||
priorDown.remove(refPos[mReferencePosition.nodeNumber * 4 + 2]);
|
|
||||||
priorDown.remove(refPos[mReferencePosition.nodeNumber * 4 + 3]);
|
|
||||||
|
|
||||||
LinkedList<ReferencePosition> linkedRef = new LinkedList<ReferencePosition>();
|
|
||||||
|
|
||||||
while (priorDown.size() != 0) {
|
|
||||||
if (priorDown.peek().x < mReferencePosition.x + mReferencePosition.width) {
|
|
||||||
linkedRef.add(priorDown.remove());
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// brute Force collision test (faster then sweep line for a small
|
|
||||||
// amount of
|
|
||||||
// objects)
|
|
||||||
for (int i = 0; i < linkedRef.size(); i++) {
|
|
||||||
if ((linkedRef.get(i).x <= mReferencePosition.x + mReferencePosition.width)
|
|
||||||
&& (linkedRef.get(i).y >= mReferencePosition.y - linkedRef.get(i).height)
|
|
||||||
&& (linkedRef.get(i).y <= mReferencePosition.y + linkedRef.get(i).height)) {
|
|
||||||
priorUp.remove(linkedRef.get(i));
|
|
||||||
linkedRef.remove(i);
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
priorDown.addAll(linkedRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolutionSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method uses an adapted greedy strategy for the fixed two position model, above and under. It uses no
|
|
||||||
* priority search tree, because it will not function with symbols only with points. Instead it uses two minimum
|
|
||||||
* heaps. They work similar to a sweep line algorithm but have not a O(n log n +k) runtime. To find the rectangle
|
|
||||||
* that has the leftest edge, I use also a minimum Heap. The rectangles are sorted by their x coordinates.
|
|
||||||
*
|
|
||||||
* @param labels
|
|
||||||
* label positions and text
|
|
||||||
* @param symbols
|
|
||||||
* symbol positions
|
|
||||||
* @param areaLabels
|
|
||||||
* area label positions and text
|
|
||||||
* @return list of labels without overlaps with symbols and other labels by the two fixed position greedy strategy
|
|
||||||
*/
|
|
||||||
private List<PointTextContainer> processTwoPointGreedy(List<PointTextContainer> labels,
|
|
||||||
List<SymbolContainer> symbols, List<PointTextContainer> areaLabels) {
|
|
||||||
List<PointTextContainer> resolutionSet = new ArrayList<PointTextContainer>();
|
|
||||||
// Array for the generated reference positions around the points of
|
|
||||||
// interests
|
|
||||||
ReferencePosition[] refPos = new ReferencePosition[labels.size() * 2];
|
|
||||||
|
|
||||||
// lists that sorts the reference points after the minimum right edge x
|
|
||||||
// position
|
|
||||||
PriorityQueue<ReferencePosition> priorRight = new PriorityQueue<ReferencePosition>(labels.size() * 2
|
|
||||||
+ labels.size() / 10 * 2, ReferencePositionWidthComparator.INSTANCE);
|
|
||||||
// lists that sorts the reference points after the minimum left edge x
|
|
||||||
// position
|
|
||||||
PriorityQueue<ReferencePosition> priorLeft = new PriorityQueue<ReferencePosition>(labels.size() * 2
|
|
||||||
+ labels.size() / 10 * 2, ReferencePositionXComparator.INSTANCE);
|
|
||||||
|
|
||||||
// creates the reference positions
|
|
||||||
for (int z = 0; z < labels.size(); z++) {
|
|
||||||
mLabel = labels.get(z);
|
|
||||||
|
|
||||||
if (mLabel.symbol != null) {
|
|
||||||
refPos[z * 2] = new ReferencePosition(mLabel.x - (mLabel.boundary.width() / 2) - 0.1f,
|
|
||||||
mLabel.y - mLabel.boundary.height() - mStartDistanceToSymbols, z,
|
|
||||||
mLabel.boundary.width(), mLabel.boundary.height(), mLabel.symbol);
|
|
||||||
refPos[z * 2 + 1] = new ReferencePosition(mLabel.x - (mLabel.boundary.width() / 2),
|
|
||||||
mLabel.y + mLabel.symbol.symbol.getHeight() + mStartDistanceToSymbols, z,
|
|
||||||
mLabel.boundary.width(), mLabel.boundary.height(), mLabel.symbol);
|
|
||||||
} else {
|
|
||||||
refPos[z * 2] = new ReferencePosition(mLabel.x - (mLabel.boundary.width() / 2) - 0.1f,
|
|
||||||
mLabel.y, z, mLabel.boundary.width(), mLabel.boundary.height(), null);
|
|
||||||
refPos[z * 2 + 1] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// removes reference positions that overlaps with other symbols or
|
|
||||||
// dependency objects
|
|
||||||
removeNonValidateReferencePosition(refPos, symbols, areaLabels);
|
|
||||||
|
|
||||||
for (int i = 0; i < refPos.length; i++) {
|
|
||||||
mReferencePosition = refPos[i];
|
|
||||||
if (mReferencePosition != null) {
|
|
||||||
priorLeft.add(mReferencePosition);
|
|
||||||
priorRight.add(mReferencePosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (priorRight.size() != 0) {
|
|
||||||
mReferencePosition = priorRight.remove();
|
|
||||||
|
|
||||||
mLabel = labels.get(mReferencePosition.nodeNumber);
|
|
||||||
|
|
||||||
resolutionSet.add(new PointTextContainer(mLabel.text, mReferencePosition.x,
|
|
||||||
mReferencePosition.y, mLabel.paintFront, mLabel.paintBack,
|
|
||||||
mReferencePosition.symbol));
|
|
||||||
|
|
||||||
// Removes the other position that is a possible position for the label
|
|
||||||
// of one point
|
|
||||||
// of interest
|
|
||||||
|
|
||||||
priorRight.remove(refPos[mReferencePosition.nodeNumber * 2 + 1]);
|
|
||||||
|
|
||||||
if (priorRight.size() == 0) {
|
|
||||||
return resolutionSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
priorLeft.remove(mReferencePosition);
|
|
||||||
priorLeft.remove(refPos[mReferencePosition.nodeNumber * 2 + 1]);
|
|
||||||
|
|
||||||
// find overlapping labels and deletes the reference points and delete
|
|
||||||
// them
|
|
||||||
LinkedList<ReferencePosition> linkedRef = new LinkedList<ReferencePosition>();
|
|
||||||
|
|
||||||
while (priorLeft.size() != 0) {
|
|
||||||
if (priorLeft.peek().x < mReferencePosition.x + mReferencePosition.width) {
|
|
||||||
linkedRef.add(priorLeft.remove());
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// brute Force collision test (faster then sweep line for a small
|
|
||||||
// amount of
|
|
||||||
// objects)
|
|
||||||
for (int i = 0; i < linkedRef.size(); i++) {
|
|
||||||
if ((linkedRef.get(i).x <= mReferencePosition.x + mReferencePosition.width)
|
|
||||||
&& (linkedRef.get(i).y >= mReferencePosition.y - linkedRef.get(i).height)
|
|
||||||
&& (linkedRef.get(i).y <= mReferencePosition.y + linkedRef.get(i).height)) {
|
|
||||||
priorRight.remove(linkedRef.get(i));
|
|
||||||
linkedRef.remove(i);
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
priorLeft.addAll(linkedRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolutionSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeEmptySymbolReferences(List<PointTextContainer> nodes, List<SymbolContainer> symbols) {
|
|
||||||
for (int i = 0; i < nodes.size(); i++) {
|
|
||||||
mLabel = nodes.get(i);
|
|
||||||
if (!symbols.contains(mLabel.symbol)) {
|
|
||||||
mLabel.symbol = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The greedy algorithms need possible label positions, to choose the best among them. This method removes the
|
|
||||||
* reference points, that are not validate. Not validate means, that the Reference overlap with another symbol or
|
|
||||||
* label or is outside of the tile.
|
|
||||||
*
|
|
||||||
* @param refPos
|
|
||||||
* list of the potential positions
|
|
||||||
* @param symbols
|
|
||||||
* actual list of the symbols
|
|
||||||
* @param areaLabels
|
|
||||||
* actual list of the area labels
|
|
||||||
*/
|
|
||||||
private void removeNonValidateReferencePosition(ReferencePosition[] refPos, List<SymbolContainer> symbols,
|
|
||||||
List<PointTextContainer> areaLabels) {
|
|
||||||
int dis = mLabelDistanceToSymbol;
|
|
||||||
|
|
||||||
for (int i = 0; i < symbols.size(); i++) {
|
|
||||||
mSymbolContainer = symbols.get(i);
|
|
||||||
mRect1.set((int) mSymbolContainer.x - dis, (int) mSymbolContainer.y - dis,
|
|
||||||
(int) mSymbolContainer.x + mSymbolContainer.symbol.getWidth() + dis,
|
|
||||||
(int) mSymbolContainer.y + mSymbolContainer.symbol.getHeight() + dis);
|
|
||||||
|
|
||||||
for (int y = 0; y < refPos.length; y++) {
|
|
||||||
if (refPos[y] != null) {
|
|
||||||
|
|
||||||
mRect2.set((int) refPos[y].x, (int) (refPos[y].y - refPos[y].height),
|
|
||||||
(int) (refPos[y].x + refPos[y].width), (int) (refPos[y].y));
|
|
||||||
|
|
||||||
if (android.graphics.Rect.intersects(mRect2, mRect1)) {
|
|
||||||
refPos[y] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dis = mLabelDistanceToLabel;
|
|
||||||
|
|
||||||
for (PointTextContainer areaLabel : areaLabels) {
|
|
||||||
|
|
||||||
mRect1.set((int) areaLabel.x - dis, (int) areaLabel.y - areaLabel.boundary.height() - dis,
|
|
||||||
(int) areaLabel.x + areaLabel.boundary.width() + dis, (int) areaLabel.y + dis);
|
|
||||||
|
|
||||||
for (int y = 0; y < refPos.length; y++) {
|
|
||||||
if (refPos[y] != null) {
|
|
||||||
|
|
||||||
mRect2.set((int) refPos[y].x, (int) (refPos[y].y - refPos[y].height),
|
|
||||||
(int) (refPos[y].x + refPos[y].width), (int) (refPos[y].y));
|
|
||||||
|
|
||||||
if (android.graphics.Rect.intersects(mRect2, mRect1)) {
|
|
||||||
refPos[y] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mDependencyCache.removeReferencePointsFromDependencyCache(refPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method removes the area labels, that are not visible in the actual tile.
|
|
||||||
*
|
|
||||||
* @param areaLabels
|
|
||||||
* area Labels from the actual tile
|
|
||||||
*/
|
|
||||||
private void removeOutOfTileAreaLabels(List<PointTextContainer> areaLabels) {
|
|
||||||
for (int i = 0; i < areaLabels.size(); i++) {
|
|
||||||
mLabel = areaLabels.get(i);
|
|
||||||
|
|
||||||
if (mLabel.x > Tile.TILE_SIZE) {
|
|
||||||
areaLabels.remove(i);
|
|
||||||
|
|
||||||
i--;
|
|
||||||
} else if (mLabel.y - mLabel.boundary.height() > Tile.TILE_SIZE) {
|
|
||||||
areaLabels.remove(i);
|
|
||||||
|
|
||||||
i--;
|
|
||||||
} else if (mLabel.x + mLabel.boundary.width() < 0.0f) {
|
|
||||||
areaLabels.remove(i);
|
|
||||||
|
|
||||||
i--;
|
|
||||||
} else if (mLabel.y + mLabel.boundary.height() < 0.0f) {
|
|
||||||
areaLabels.remove(i);
|
|
||||||
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method removes the labels, that are not visible in the actual tile.
|
|
||||||
*
|
|
||||||
* @param labels
|
|
||||||
* Labels from the actual tile
|
|
||||||
*/
|
|
||||||
private void removeOutOfTileLabels(List<PointTextContainer> labels) {
|
|
||||||
for (int i = 0; i < labels.size();) {
|
|
||||||
mLabel = labels.get(i);
|
|
||||||
|
|
||||||
if (mLabel.x - mLabel.boundary.width() / 2 > Tile.TILE_SIZE) {
|
|
||||||
labels.remove(i);
|
|
||||||
mLabel = null;
|
|
||||||
} else if (mLabel.y - mLabel.boundary.height() > Tile.TILE_SIZE) {
|
|
||||||
labels.remove(i);
|
|
||||||
mLabel = null;
|
|
||||||
} else if ((mLabel.x - mLabel.boundary.width() / 2 + mLabel.boundary.width()) < 0.0f) {
|
|
||||||
labels.remove(i);
|
|
||||||
mLabel = null;
|
|
||||||
} else if (mLabel.y < 0.0f) {
|
|
||||||
labels.remove(i);
|
|
||||||
mLabel = null;
|
|
||||||
} else {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method removes the Symbols, that are not visible in the actual tile.
|
|
||||||
*
|
|
||||||
* @param symbols
|
|
||||||
* Symbols from the actual tile
|
|
||||||
*/
|
|
||||||
private void removeOutOfTileSymbols(List<SymbolContainer> symbols) {
|
|
||||||
for (int i = 0; i < symbols.size();) {
|
|
||||||
mSymbolContainer = symbols.get(i);
|
|
||||||
|
|
||||||
if (mSymbolContainer.x > Tile.TILE_SIZE) {
|
|
||||||
symbols.remove(i);
|
|
||||||
} else if (mSymbolContainer.y > Tile.TILE_SIZE) {
|
|
||||||
symbols.remove(i);
|
|
||||||
} else if (mSymbolContainer.x + mSymbolContainer.symbol.getWidth() < 0.0f) {
|
|
||||||
symbols.remove(i);
|
|
||||||
} else if (mSymbolContainer.y + mSymbolContainer.symbol.getHeight() < 0.0f) {
|
|
||||||
symbols.remove(i);
|
|
||||||
} else {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method removes all the area labels, that overlap each other. So that the output is collision free
|
|
||||||
*
|
|
||||||
* @param areaLabels
|
|
||||||
* area labels from the actual tile
|
|
||||||
*/
|
|
||||||
private void removeOverlappingAreaLabels(List<PointTextContainer> areaLabels) {
|
|
||||||
int dis = mLabelDistanceToLabel;
|
|
||||||
|
|
||||||
for (int x = 0; x < areaLabels.size(); x++) {
|
|
||||||
mLabel = areaLabels.get(x);
|
|
||||||
mRect1.set((int) mLabel.x - dis, (int) mLabel.y - dis,
|
|
||||||
(int) (mLabel.x + mLabel.boundary.width()) + dis,
|
|
||||||
(int) (mLabel.y + mLabel.boundary.height() + dis));
|
|
||||||
|
|
||||||
for (int y = x + 1; y < areaLabels.size(); y++) {
|
|
||||||
if (y != x) {
|
|
||||||
mLabel = areaLabels.get(y);
|
|
||||||
mRect2.set((int) mLabel.x, (int) mLabel.y,
|
|
||||||
(int) (mLabel.x + mLabel.boundary.width()),
|
|
||||||
(int) (mLabel.y + mLabel.boundary.height()));
|
|
||||||
|
|
||||||
if (android.graphics.Rect.intersects(mRect1, mRect2)) {
|
|
||||||
areaLabels.remove(y);
|
|
||||||
|
|
||||||
y--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the the symbols that overlap with area labels.
|
|
||||||
*
|
|
||||||
* @param symbols
|
|
||||||
* list of symbols
|
|
||||||
* @param pTC
|
|
||||||
* list of labels
|
|
||||||
*/
|
|
||||||
private void removeOverlappingSymbolsWithAreaLabels(List<SymbolContainer> symbols, List<PointTextContainer> pTC) {
|
|
||||||
int dis = mLabelDistanceToSymbol;
|
|
||||||
|
|
||||||
for (int x = 0; x < pTC.size(); x++) {
|
|
||||||
mLabel = pTC.get(x);
|
|
||||||
|
|
||||||
mRect1.set((int) mLabel.x - dis, (int) (mLabel.y - mLabel.boundary.height()) - dis,
|
|
||||||
(int) (mLabel.x + mLabel.boundary.width() + dis), (int) (mLabel.y + dis));
|
|
||||||
|
|
||||||
for (int y = 0; y < symbols.size(); y++) {
|
|
||||||
mSymbolContainer = symbols.get(y);
|
|
||||||
|
|
||||||
mRect2.set((int) mSymbolContainer.x, (int) mSymbolContainer.y,
|
|
||||||
(int) (mSymbolContainer.x + mSymbolContainer.symbol.getWidth()),
|
|
||||||
(int) (mSymbolContainer.y + mSymbolContainer.symbol.getHeight()));
|
|
||||||
|
|
||||||
if (android.graphics.Rect.intersects(mRect1, mRect2)) {
|
|
||||||
symbols.remove(y);
|
|
||||||
y--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int getLabelDistanceToLabel() {
|
|
||||||
return mLabelDistanceToLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getLabelDistanceToSymbol() {
|
|
||||||
return mLabelDistanceToSymbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPlacementOption() {
|
|
||||||
return PLACEMENT_MODEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getStartDistanceToSymbols() {
|
|
||||||
return mStartDistanceToSymbols;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getSymbolDistanceToSymbol() {
|
|
||||||
return mSymbolDistanceToSymbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The inputs are all the label and symbol objects of the current tile. The output is overlap free label and symbol
|
|
||||||
* placement with the greedy strategy. The placement model is either the two fixed point or the four fixed point
|
|
||||||
* model.
|
|
||||||
*
|
|
||||||
* @param labels
|
|
||||||
* labels from the current tile.
|
|
||||||
* @param symbols
|
|
||||||
* symbols of the current tile.
|
|
||||||
* @param areaLabels
|
|
||||||
* area labels from the current tile.
|
|
||||||
* @param cT
|
|
||||||
* current tile with the x,y- coordinates and the zoom level.
|
|
||||||
* @return the processed list of labels.
|
|
||||||
*/
|
|
||||||
List<PointTextContainer> placeLabels(List<PointTextContainer> labels, List<SymbolContainer> symbols,
|
|
||||||
List<PointTextContainer> areaLabels, Tile cT) {
|
|
||||||
List<PointTextContainer> returnLabels = labels;
|
|
||||||
mDependencyCache.generateTileAndDependencyOnTile(cT);
|
|
||||||
|
|
||||||
preprocessAreaLabels(areaLabels);
|
|
||||||
|
|
||||||
preprocessLabels(returnLabels);
|
|
||||||
|
|
||||||
preprocessSymbols(symbols);
|
|
||||||
|
|
||||||
removeEmptySymbolReferences(returnLabels, symbols);
|
|
||||||
|
|
||||||
removeOverlappingSymbolsWithAreaLabels(symbols, areaLabels);
|
|
||||||
|
|
||||||
mDependencyCache.removeOverlappingObjectsWithDependencyOnTile(returnLabels, areaLabels, symbols);
|
|
||||||
|
|
||||||
if (!returnLabels.isEmpty()) {
|
|
||||||
switch (PLACEMENT_MODEL) {
|
|
||||||
case 0:
|
|
||||||
returnLabels = processTwoPointGreedy(returnLabels, symbols, areaLabels);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
returnLabels = processFourPointGreedy(returnLabels, symbols, areaLabels);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mDependencyCache.fillDependencyOnTile(returnLabels, symbols, areaLabels);
|
|
||||||
|
|
||||||
return returnLabels;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method removes all the Symbols, that overlap each other. So that the output is collision free.
|
|
||||||
*
|
|
||||||
* @param symbols
|
|
||||||
* symbols from the actual tile
|
|
||||||
*/
|
|
||||||
void removeOverlappingSymbols(List<SymbolContainer> symbols) {
|
|
||||||
int dis = mSymbolDistanceToSymbol;
|
|
||||||
|
|
||||||
for (int x = 0; x < symbols.size(); x++) {
|
|
||||||
mSymbolContainer = symbols.get(x);
|
|
||||||
mRect1.set((int) mSymbolContainer.x - dis, (int) mSymbolContainer.y - dis,
|
|
||||||
(int) mSymbolContainer.x + mSymbolContainer.symbol.getWidth() + dis,
|
|
||||||
(int) mSymbolContainer.y + mSymbolContainer.symbol.getHeight() + dis);
|
|
||||||
|
|
||||||
for (int y = x + 1; y < symbols.size(); y++) {
|
|
||||||
if (y != x) {
|
|
||||||
mSymbolContainer = symbols.get(y);
|
|
||||||
mRect2.set((int) mSymbolContainer.x, (int) mSymbolContainer.y,
|
|
||||||
(int) mSymbolContainer.x + mSymbolContainer.symbol.getWidth(),
|
|
||||||
(int) mSymbolContainer.y + mSymbolContainer.symbol.getHeight());
|
|
||||||
|
|
||||||
if (android.graphics.Rect.intersects(mRect2, mRect1)) {
|
|
||||||
symbols.remove(y);
|
|
||||||
y--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLabelDistanceToLabel(int labelDistanceToLabel) {
|
|
||||||
mLabelDistanceToLabel = labelDistanceToLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLabelDistanceToSymbol(int labelDistanceToSymbol) {
|
|
||||||
mLabelDistanceToSymbol = labelDistanceToSymbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStartDistanceToSymbols(int startDistanceToSymbols) {
|
|
||||||
mStartDistanceToSymbols = startDistanceToSymbols;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSymbolDistanceToSymbol(int symbolDistanceToSymbol) {
|
|
||||||
mSymbolDistanceToSymbol = symbolDistanceToSymbol;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
import android.graphics.Paint;
|
|
||||||
|
|
||||||
class LayerContainer {
|
|
||||||
|
|
||||||
final LevelContainer[] mLevels;
|
|
||||||
final boolean[] mLevelActive;
|
|
||||||
boolean mActive;
|
|
||||||
|
|
||||||
LayerContainer(int levels) {
|
|
||||||
mLevels = new LevelContainer[levels];
|
|
||||||
mLevelActive = new boolean[levels];
|
|
||||||
mActive = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ShapeContainer> add(int level, ShapeContainer shapeContainer, Paint paint) {
|
|
||||||
mActive = true;
|
|
||||||
LevelContainer levelContainer = mLevels[level];
|
|
||||||
if (levelContainer == null) {
|
|
||||||
levelContainer = new LevelContainer();
|
|
||||||
mLevels[level] = levelContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
levelContainer.add(shapeContainer, paint);
|
|
||||||
|
|
||||||
mLevelActive[level] = true;
|
|
||||||
|
|
||||||
return levelContainer.mShapeContainers;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
if (!mActive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mActive = false;
|
|
||||||
|
|
||||||
for (int level = mLevels.length - 1; level >= 0; level--) {
|
|
||||||
if (mLevelActive[level]) {
|
|
||||||
LevelContainer levelContainer = mLevels[level];
|
|
||||||
mLevelActive[level] = false;
|
|
||||||
levelContainer.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
|
|
||||||
import android.graphics.Paint;
|
|
||||||
|
|
||||||
class LevelContainer {
|
|
||||||
final ArrayList<ShapeContainer> mShapeContainers;
|
|
||||||
Paint[] mPaint;
|
|
||||||
|
|
||||||
LevelContainer() {
|
|
||||||
mShapeContainers = new ArrayList<ShapeContainer>(20);
|
|
||||||
mPaint = new Paint[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
void add(ShapeContainer shapeContainer, Paint paint) {
|
|
||||||
if (mPaint[0] == null)
|
|
||||||
mPaint[0] = paint;
|
|
||||||
else if (mPaint[0] != paint)
|
|
||||||
mPaint[1] = paint;
|
|
||||||
|
|
||||||
mShapeContainers.add(shapeContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
mShapeContainers.clear();
|
|
||||||
mPaint[0] = null;
|
|
||||||
mPaint[1] = null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,541 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.oscim.core.Tag;
|
|
||||||
import org.oscim.core.Tile;
|
|
||||||
import org.oscim.database.IMapDatabase;
|
|
||||||
import org.oscim.database.IMapDatabaseCallback;
|
|
||||||
import org.oscim.database.mapfile.MapDatabase;
|
|
||||||
import org.oscim.theme.IRenderCallback;
|
|
||||||
import org.oscim.theme.RenderTheme;
|
|
||||||
import org.oscim.theme.renderinstruction.Area;
|
|
||||||
import org.oscim.theme.renderinstruction.Caption;
|
|
||||||
import org.oscim.theme.renderinstruction.Line;
|
|
||||||
import org.oscim.theme.renderinstruction.PathText;
|
|
||||||
import org.oscim.view.DebugSettings;
|
|
||||||
import org.oscim.view.MapView;
|
|
||||||
import org.oscim.view.mapgenerator.IMapGenerator;
|
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.util.FloatMath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A DatabaseRenderer renders map tiles by reading from a {@link MapDatabase}.
|
|
||||||
*/
|
|
||||||
public class MapGenerator implements IMapGenerator, IRenderCallback,
|
|
||||||
IMapDatabaseCallback {
|
|
||||||
// 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 byte getValidLayer(byte layer) {
|
|
||||||
if (layer < 0) {
|
|
||||||
return 0;
|
|
||||||
} else if (layer >= LAYERS) {
|
|
||||||
return LAYERS - 1;
|
|
||||||
} else {
|
|
||||||
return layer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final CanvasRasterer mCanvasRasterer;
|
|
||||||
|
|
||||||
private LayerContainer mDrawingLayer;
|
|
||||||
private final LabelPlacement mLabelPlacement;
|
|
||||||
private IMapDatabase mMapDatabase;
|
|
||||||
private List<PointTextContainer> mNodes;
|
|
||||||
private float mPoiX;
|
|
||||||
private float mPoiY;
|
|
||||||
// private Theme mPreviousJobTheme;
|
|
||||||
// private float mPreviousTextScale;
|
|
||||||
// private byte mPreviousZoomLevel;
|
|
||||||
private static RenderTheme renderTheme;
|
|
||||||
|
|
||||||
private final List<WayTextContainer> mWayNames;
|
|
||||||
private final LayerContainer[] mWays;
|
|
||||||
private final List<SymbolContainer> mWaySymbols;
|
|
||||||
private final List<SymbolContainer> mPointSymbols;
|
|
||||||
private final List<PointTextContainer> mAreaLabels;
|
|
||||||
|
|
||||||
// private float mLat1, mLat2, mLon1, mLon2;
|
|
||||||
// private float mTileWidth, mTileHeight;
|
|
||||||
private float mScale;
|
|
||||||
|
|
||||||
// private float[] mCoordinates;
|
|
||||||
private WayDataContainer mWayDataContainer;
|
|
||||||
private final Bitmap mTileBitmap;
|
|
||||||
|
|
||||||
private static float PI180 = (float) (Math.PI / 180) / 1000000.0f;
|
|
||||||
private static float PIx4 = (float) Math.PI * 4;
|
|
||||||
|
|
||||||
private JobTile mCurrentTile;
|
|
||||||
private static long mCurrentTileY;
|
|
||||||
private static long mCurrentTileX;
|
|
||||||
private static long mCurrentTileZoom;
|
|
||||||
|
|
||||||
private float[] mCoords = null;
|
|
||||||
|
|
||||||
// private long _renderTime;
|
|
||||||
private int _nodes, _nodesDropped;
|
|
||||||
private MapView mMapView;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new DatabaseRenderer.
|
|
||||||
*
|
|
||||||
* @param mapView
|
|
||||||
* the MapView
|
|
||||||
*/
|
|
||||||
public MapGenerator(MapView mapView) {
|
|
||||||
mMapView = mapView;
|
|
||||||
mCanvasRasterer = new CanvasRasterer();
|
|
||||||
mLabelPlacement = new LabelPlacement();
|
|
||||||
|
|
||||||
mWays = new LayerContainer[LAYERS];
|
|
||||||
mWayNames = new ArrayList<WayTextContainer>(64);
|
|
||||||
mNodes = new ArrayList<PointTextContainer>(64);
|
|
||||||
mAreaLabels = new ArrayList<PointTextContainer>(64);
|
|
||||||
mWaySymbols = new ArrayList<SymbolContainer>(64);
|
|
||||||
mPointSymbols = new ArrayList<SymbolContainer>(64);
|
|
||||||
|
|
||||||
PAINT_WATER_TILE_HIGHTLIGHT.setStyle(Paint.Style.FILL);
|
|
||||||
PAINT_WATER_TILE_HIGHTLIGHT.setColor(Color.CYAN);
|
|
||||||
// mCoordinates = new float[1024];
|
|
||||||
|
|
||||||
mTileBitmap = Bitmap.createBitmap(Tile.TILE_SIZE * 2, Tile.TILE_SIZE * 2,
|
|
||||||
Bitmap.Config.RGB_565);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cleanup() {
|
|
||||||
mTileBitmap.recycle();
|
|
||||||
if (MapGenerator.renderTheme != null) {
|
|
||||||
MapGenerator.renderTheme.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean executeJob(JobTile jobTile) {
|
|
||||||
long time_load = System.currentTimeMillis();
|
|
||||||
_nodes = 0;
|
|
||||||
_nodesDropped = 0;
|
|
||||||
// _renderTime = 0;
|
|
||||||
|
|
||||||
mCurrentTile = jobTile;
|
|
||||||
mCurrentTileZoom = ((long) Tile.TILE_SIZE << mCurrentTile.zoomLevel);
|
|
||||||
mCurrentTileX = mCurrentTile.pixelX;
|
|
||||||
mCurrentTileY = mCurrentTile.pixelY;
|
|
||||||
|
|
||||||
// mLon1 = (float) MercatorProjection.pixelXToLongitude(mCurrentTileX, mCurrentTile.zoomLevel) * 1000000;
|
|
||||||
// mLat1 = (float) MercatorProjection.pixelYToLatitude(mCurrentTileY, mCurrentTile.zoomLevel) * 1000000;
|
|
||||||
// mLon2 = (float) MercatorProjection.pixelXToLongitude(mCurrentTileX + Tile.TILE_SIZE, mCurrentTile.zoomLevel)
|
|
||||||
// * 1000000;
|
|
||||||
// mLat2 = (float) MercatorProjection.pixelYToLatitude(mCurrentTileY + Tile.TILE_SIZE, mCurrentTile.zoomLevel) *
|
|
||||||
// 1000000;
|
|
||||||
//
|
|
||||||
// mTileWidth = mLon2 - mLon1;
|
|
||||||
// mTileHeight = mLat1 - mLat2;
|
|
||||||
// mScale = mapGeneratorJob.getScale();
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
time_load = System.currentTimeMillis() - time_load;
|
|
||||||
|
|
||||||
mNodes = mLabelPlacement.placeLabels(mNodes, mPointSymbols, mAreaLabels,
|
|
||||||
mCurrentTile);
|
|
||||||
|
|
||||||
long time_draw = System.currentTimeMillis();
|
|
||||||
|
|
||||||
// FIXME mCoords = mMapDatabase.getCoordinates();
|
|
||||||
|
|
||||||
mCanvasRasterer.setCanvasBitmap(mTileBitmap, mScale);
|
|
||||||
mCanvasRasterer.fill(MapGenerator.renderTheme.getMapBackground());
|
|
||||||
mCanvasRasterer.drawWays(mCoords, mWays);
|
|
||||||
mCanvasRasterer.drawSymbols(mWaySymbols);
|
|
||||||
mCanvasRasterer.drawSymbols(mPointSymbols);
|
|
||||||
mCanvasRasterer.drawWayNames(mCoords, mWayNames);
|
|
||||||
mCanvasRasterer.drawNodes(mNodes);
|
|
||||||
mCanvasRasterer.drawNodes(mAreaLabels);
|
|
||||||
time_draw = System.currentTimeMillis() - time_draw;
|
|
||||||
|
|
||||||
DebugSettings debugSettings = mMapView.getDebugSettings();
|
|
||||||
|
|
||||||
if (debugSettings.mDrawTileFrames) {
|
|
||||||
mCanvasRasterer.drawTileFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debugSettings.mDrawTileCoordinates) {
|
|
||||||
mCanvasRasterer.drawTileCoordinates(mCurrentTile, time_load, time_draw,
|
|
||||||
_nodes, _nodesDropped);
|
|
||||||
}
|
|
||||||
|
|
||||||
clearLists();
|
|
||||||
|
|
||||||
// mapGeneratorJob.setBitmap(mTileBitmap);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderAreaCaption(Caption caption) {
|
|
||||||
// mapDatabase.readTag(caption);
|
|
||||||
// if (caption.value != null) {
|
|
||||||
// float[] centerPosition = GeometryUtils
|
|
||||||
// .calculateCenterOfBoundingBox(coordinates[0]);
|
|
||||||
// areaLabels.add(new PointTextContainer(caption.value,
|
|
||||||
// centerPosition[0],
|
|
||||||
// centerPosition[1],
|
|
||||||
// paint, stroke));
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderAreaSymbol(Bitmap symbol) {
|
|
||||||
// float[] centerPosition = GeometryUtils
|
|
||||||
// .calculateCenterOfBoundingBox(coordinates[0]);
|
|
||||||
// pointSymbols.add(new SymbolContainer(symbol, centerPosition[0]
|
|
||||||
// - (symbol.getWidth() >> 1), centerPosition[1]
|
|
||||||
// - (symbol.getHeight() >> 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderPointOfInterest(byte layer, float latitude, float longitude,
|
|
||||||
Tag[] tags) {
|
|
||||||
mDrawingLayer = mWays[getValidLayer(layer)];
|
|
||||||
mPoiX = scaleLongitude(longitude);
|
|
||||||
mPoiY = scaleLatitude(latitude);
|
|
||||||
MapGenerator.renderTheme.matchNode(this, tags, mCurrentTile.zoomLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderPointOfInterestCaption(Caption caption) {
|
|
||||||
// mapDatabase.readTag(caption);
|
|
||||||
// if (caption.value != null) {
|
|
||||||
// nodes.add(new PointTextContainer(caption.value, poiX, poiY + verticalOffset, paint, stroke));
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderPointOfInterestCircle(float radius, Paint outline, int level) {
|
|
||||||
|
|
||||||
mDrawingLayer.add(level, new CircleContainer(mPoiX, mPoiY, radius), outline);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderPointOfInterestSymbol(Bitmap symbol) {
|
|
||||||
mPointSymbols.add(new SymbolContainer(symbol, mPoiX - (symbol.getWidth() >> 1),
|
|
||||||
mPoiY
|
|
||||||
- (symbol.getHeight() >> 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderWaterBackground() {
|
|
||||||
// if (mCoords == null)
|
|
||||||
// mCoords = mMapDatabase.getCoordinates();
|
|
||||||
|
|
||||||
// float[] coords = mCoords;
|
|
||||||
//
|
|
||||||
// mDrawingLayer = mWays[5];
|
|
||||||
//
|
|
||||||
// int len = wayData.length[0];
|
|
||||||
// int pos = wayData.position[0];
|
|
||||||
//
|
|
||||||
// for (int j = pos, m = pos + len; j < m; j += 2) {
|
|
||||||
// coords[j] = coords[j] * mScale;
|
|
||||||
// coords[j + 1] = coords[j + 1] * mScale;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// mWayDataContainer = wayData;
|
|
||||||
//
|
|
||||||
// Log.i("mapsforge", "render water");
|
|
||||||
//
|
|
||||||
// DatabaseRenderer.renderTheme.matchWay(this, tags, mCurrentTile.zoomLevel, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// private boolean mPrevClosed = false;
|
|
||||||
// private byte mPrevLayer = 0;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLengths,
|
|
||||||
boolean changed) {
|
|
||||||
// if (mCoords == null)
|
|
||||||
// mCoords = mMapDatabase.getCoordinates();
|
|
||||||
|
|
||||||
// float[] coords = mCoords;
|
|
||||||
//
|
|
||||||
// boolean closed = false;
|
|
||||||
// boolean added = false;
|
|
||||||
//
|
|
||||||
// // coordinatesLength = wayData.length.length;
|
|
||||||
// if (mCurrentTile.zoomLevel < 6) {
|
|
||||||
// long x = mCurrentTileX;
|
|
||||||
// long y = mCurrentTileY;
|
|
||||||
// long z = mCurrentTileZoom;
|
|
||||||
// float s = mScale;
|
|
||||||
//
|
|
||||||
// added = true;
|
|
||||||
//
|
|
||||||
// for (int i = wayData.length.length - 1; i >= 0; i--) {
|
|
||||||
// int len = wayData.length[i];
|
|
||||||
// int pos = wayData.position[i];
|
|
||||||
//
|
|
||||||
// if (i == 0)
|
|
||||||
// closed = (coords[pos] == coords[(pos + len) - 2] &&
|
|
||||||
// coords[pos + 1] == coords[(pos + len) - 1]);
|
|
||||||
//
|
|
||||||
// for (int j = pos, m = pos + len; j < m; j += 2) {
|
|
||||||
//
|
|
||||||
// coords[j] = (float) (((coords[j] / 1000000.0 + 180) / 360 * z) - x) * s;
|
|
||||||
//
|
|
||||||
// double sinLat = Math.sin(coords[j + 1] * PI180);
|
|
||||||
// coords[j + 1] = (float) ((0.5 - Math.log((1 + sinLat) / (1 - sinLat)) / PIx4) * z - y) * s;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// // use linear approximation on high zoom levels.
|
|
||||||
// float ssize = Tile.TILE_SIZE * mScale;
|
|
||||||
// float sw = ssize / mTileWidth;
|
|
||||||
// float sh = ssize / mTileHeight;
|
|
||||||
// int j, o;
|
|
||||||
// float x, y;
|
|
||||||
//
|
|
||||||
// int min = 1;
|
|
||||||
// if (mCurrentTile.zoomLevel < 14)
|
|
||||||
// min = 3;
|
|
||||||
// else if (mCurrentTile.zoomLevel < 9)
|
|
||||||
// min = 5;
|
|
||||||
//
|
|
||||||
// for (int i = wayData.length.length - 1; i >= 0; i--) {
|
|
||||||
//
|
|
||||||
// int len = wayData.length[i];
|
|
||||||
// int pos = wayData.position[i];
|
|
||||||
// _nodes += len / 2;
|
|
||||||
//
|
|
||||||
// if (i == 0) {
|
|
||||||
// closed = (coords[pos] == coords[(pos + len) - 2] &&
|
|
||||||
// coords[pos + 1] == coords[(pos + len) - 1]);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// coords[pos] = (coords[pos] - mLon1) * sw;
|
|
||||||
// coords[pos + 1] = ssize - (coords[pos + 1] - mLat2) * sh;
|
|
||||||
//
|
|
||||||
// j = o = pos + 2;
|
|
||||||
//
|
|
||||||
// // drop intermediate nodes with less than 'min' distance.
|
|
||||||
// for (int m = pos + len - 2; j < m; j += 2) {
|
|
||||||
// x = (coords[j] - mLon1) * sw;
|
|
||||||
// y = ssize - (coords[j + 1] - mLat2) * sh;
|
|
||||||
//
|
|
||||||
// if (x > coords[o - 2] + min || x < coords[o - 2] - min ||
|
|
||||||
// y > coords[o - 1] + min || y < coords[o - 1] - min) {
|
|
||||||
//
|
|
||||||
// coords[o++] = x;
|
|
||||||
// coords[o++] = y;
|
|
||||||
// } else
|
|
||||||
// _nodesDropped++;
|
|
||||||
// }
|
|
||||||
// coords[o] = (coords[j] - mLon1) * sw;
|
|
||||||
// coords[o + 1] = ssize - (coords[j + 1] - mLat2) * sh;
|
|
||||||
// o += 2;
|
|
||||||
//
|
|
||||||
// wayData.length[i] = o - pos;
|
|
||||||
//
|
|
||||||
// if (!closed || (o - pos) > 4)
|
|
||||||
// added = true;
|
|
||||||
// else
|
|
||||||
// wayData.length[i] = 0;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (!added && !changed)
|
|
||||||
// return;
|
|
||||||
//
|
|
||||||
// mWayDataContainer = wayData;
|
|
||||||
//
|
|
||||||
// mDrawingLayer = mWays[getValidLayer(layer)];
|
|
||||||
//
|
|
||||||
// if (changed || (closed != mPrevClosed) || (layer != mPrevLayer)) {
|
|
||||||
// mCurLevelContainer1 = null;
|
|
||||||
// mCurLevelContainer2 = null;
|
|
||||||
// DatabaseRenderer.renderTheme.matchWay(this, tags, mCurrentTile.zoomLevel, closed);
|
|
||||||
// } else {
|
|
||||||
// if (mCurLevelContainer1 != null)
|
|
||||||
// mCurLevelContainer1.add(mWayDataContainer);
|
|
||||||
// if (mCurLevelContainer2 != null)
|
|
||||||
// mCurLevelContainer2.add(mWayDataContainer);
|
|
||||||
// }
|
|
||||||
// mPrevClosed = closed;
|
|
||||||
// mPrevLayer = layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// private List<ShapeContainer> mCurLevelContainer1;
|
|
||||||
// private List<ShapeContainer> mCurLevelContainer2;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderWay(Line line, int level) {
|
|
||||||
// List<ShapeContainer> c = mDrawingLayer.add(level, mWayDataContainer,
|
|
||||||
// line.paint);
|
|
||||||
//
|
|
||||||
// if (mCurLevelContainer1 == null)
|
|
||||||
// mCurLevelContainer1 = c;
|
|
||||||
// else if (mCurLevelContainer2 == null)
|
|
||||||
// mCurLevelContainer2 = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderArea(Area area, int level) {
|
|
||||||
// if (area.paintFill != null)
|
|
||||||
// mCurLevelContainer1 = mDrawingLayer.add(level, mWayDataContainer,
|
|
||||||
// area.paintFill);
|
|
||||||
// if (area.paintOutline != null)
|
|
||||||
// mCurLevelContainer1 = mDrawingLayer.add(level, mWayDataContainer,
|
|
||||||
// area.paintOutline);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderWaySymbol(Bitmap symbolBitmap, boolean alignCenter,
|
|
||||||
boolean repeatSymbol) {
|
|
||||||
// WayDecorator.renderSymbol(symbolBitmap, alignCenter, repeatSymbol,
|
|
||||||
// coordinates,
|
|
||||||
// waySymbols);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderWayText(PathText pathText) {
|
|
||||||
// if (mWayDataContainer.textPos[0] >= 0)
|
|
||||||
// WayDecorator.renderText(this, paint, outline, mCoords, mWayDataContainer, mWayNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMapDatabase(IMapDatabase mapDatabase) {
|
|
||||||
mMapDatabase = mapDatabase;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearLists() {
|
|
||||||
for (int i = LAYERS - 1; i >= 0; --i) {
|
|
||||||
mWays[i].clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
mAreaLabels.clear();
|
|
||||||
mNodes.clear();
|
|
||||||
mPointSymbols.clear();
|
|
||||||
mWayNames.clear();
|
|
||||||
mWaySymbols.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// private void createWayLists() {
|
|
||||||
// int levels = MapGenerator.renderTheme.getLevels();
|
|
||||||
// for (byte i = LAYERS - 1; i >= 0; --i) {
|
|
||||||
// mWays[i] = new LayerContainer(levels);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a latitude value into an Y coordinate on the current tile.
|
|
||||||
*
|
|
||||||
* @param latitude
|
|
||||||
* the latitude value.
|
|
||||||
* @return the Y coordinate on the current tile.
|
|
||||||
*/
|
|
||||||
private static float scaleLatitude(float latitude) {
|
|
||||||
double sinLatitude = FloatMath.sin(latitude * PI180);
|
|
||||||
|
|
||||||
return (float) (0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / PIx4)
|
|
||||||
* mCurrentTileZoom
|
|
||||||
- mCurrentTileY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a longitude value into an X coordinate on the current tile.
|
|
||||||
*
|
|
||||||
* @param longitude
|
|
||||||
* the longitude value.
|
|
||||||
* @return the X coordinate on the current tile.
|
|
||||||
*/
|
|
||||||
|
|
||||||
private static float scaleLongitude(float longitude) {
|
|
||||||
return (float) ((longitude / 1000000.0 + 180) / 360 * mCurrentTileZoom)
|
|
||||||
- mCurrentTileX;
|
|
||||||
}
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 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);
|
|
||||||
// MapGenerator.renderTheme.scaleStrokeWidth((float) Math.pow(STROKE_INCREASE,
|
|
||||||
// zoomLevelDiff));
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IMapDatabase getMapDatabase() {
|
|
||||||
return mMapDatabase;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRenderTheme(RenderTheme theme) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkWay(Tag[] tags, boolean closed) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,583 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2011 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.nio.FloatBuffer;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import javax.microedition.khronos.egl.EGLConfig;
|
|
||||||
import javax.microedition.khronos.opengles.GL10;
|
|
||||||
|
|
||||||
import org.oscim.core.MapPosition;
|
|
||||||
import org.oscim.core.MercatorProjection;
|
|
||||||
import org.oscim.core.Tile;
|
|
||||||
import org.oscim.theme.RenderTheme;
|
|
||||||
import org.oscim.view.MapView;
|
|
||||||
import org.oscim.view.mapgenerator.IMapGenerator;
|
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
|
||||||
import org.oscim.view.mapgenerator.TileDistanceSort;
|
|
||||||
import org.oscim.view.utils.GlUtils;
|
|
||||||
|
|
||||||
import android.opengl.GLES20;
|
|
||||||
import android.opengl.Matrix;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class MapRenderer implements org.oscim.view.IMapRenderer {
|
|
||||||
// private static String TAG = "MapRenderer";
|
|
||||||
|
|
||||||
private static final int FLOAT_SIZE_BYTES = 4;
|
|
||||||
private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
|
|
||||||
private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
|
|
||||||
|
|
||||||
private int mProgram;
|
|
||||||
private int muMVPMatrixHandle;
|
|
||||||
private int maPositionHandle;
|
|
||||||
private int maTextureHandle;
|
|
||||||
private int muScaleHandle;
|
|
||||||
private FloatBuffer mVertices;
|
|
||||||
private float[] mMatrix = new float[16];
|
|
||||||
|
|
||||||
private int mWidth, mHeight;
|
|
||||||
private double mDrawX, mDrawY;
|
|
||||||
private long mTileX, mTileY;
|
|
||||||
private float mMapScale;
|
|
||||||
// private DebugSettings mDebugSettings;
|
|
||||||
// private JobParameters mJobParameter;
|
|
||||||
private MapPosition mMapPosition, mPrevMapPosition;
|
|
||||||
|
|
||||||
private ArrayList<JobTile> mJobList;
|
|
||||||
|
|
||||||
ArrayList<Integer> mTextures;
|
|
||||||
MapView mMapView;
|
|
||||||
|
|
||||||
MapTile[] currentTiles;
|
|
||||||
MapTile[] newTiles;
|
|
||||||
int currentTileCnt = 0;
|
|
||||||
|
|
||||||
// private TileCacheKey mTileCacheKey;
|
|
||||||
// private LinkedHashMap<TileCacheKey, GLMapTile> mTiles;
|
|
||||||
private ArrayList<MapTile> mTileList;
|
|
||||||
|
|
||||||
private boolean processedTile = true;
|
|
||||||
|
|
||||||
private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
|
|
||||||
|
|
||||||
private boolean mInitial;
|
|
||||||
|
|
||||||
private final TileDistanceSort tileDistanceSort = new TileDistanceSort();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mapView
|
|
||||||
* the MapView
|
|
||||||
*/
|
|
||||||
public MapRenderer(MapView mapView) {
|
|
||||||
mMapView = mapView;
|
|
||||||
// mDebugSettings = mapView.getDebugSettings();
|
|
||||||
mMapScale = 1;
|
|
||||||
|
|
||||||
float[] vertices = {
|
|
||||||
0, 0, 0, 0, 0.5f,
|
|
||||||
0, 1, 0, 0, 0,
|
|
||||||
1, 0, 0, 0.5f, 0.5f,
|
|
||||||
1, 1, 0, 0.5f, 0 };
|
|
||||||
|
|
||||||
mVertices = ByteBuffer.allocateDirect(4 * TRIANGLE_VERTICES_DATA_STRIDE_BYTES)
|
|
||||||
.order(ByteOrder.nativeOrder()).asFloatBuffer();
|
|
||||||
mVertices.put(vertices);
|
|
||||||
|
|
||||||
mTextures = new ArrayList<Integer>();
|
|
||||||
mJobList = new ArrayList<JobTile>();
|
|
||||||
|
|
||||||
// mTiles = new LinkedHashMap<TileCacheKey, GLMapTile>(100);
|
|
||||||
mTileList = new ArrayList<MapTile>();
|
|
||||||
|
|
||||||
// mTileCacheKey = new TileCacheKey();
|
|
||||||
mInitial = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void limitCache(byte zoom, int remove) {
|
|
||||||
long x = mTileX;
|
|
||||||
long y = mTileY;
|
|
||||||
int diff;
|
|
||||||
|
|
||||||
for (MapTile t : mTileList) {
|
|
||||||
|
|
||||||
diff = (t.zoomLevel - zoom);
|
|
||||||
|
|
||||||
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 *= 2 * diff * diff;
|
|
||||||
} else {
|
|
||||||
t.distance = (Math.abs(t.tileX - x) + Math.abs(t.tileY - y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(mTileList, tileDistanceSort);
|
|
||||||
|
|
||||||
for (int j = mTileList.size() - 1, cnt = 0; cnt < remove; j--, cnt++) {
|
|
||||||
MapTile t = mTileList.remove(j);
|
|
||||||
|
|
||||||
// mTileCacheKey.set(t.tileX, t.tileY, t.zoomLevel);
|
|
||||||
// mTiles.remove(mTileCacheKey);
|
|
||||||
|
|
||||||
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(Integer.valueOf(t.getTexture()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean updateVisibleList(long x, long y, byte zoomLevel) {
|
|
||||||
float scale = mMapPosition.scale;
|
|
||||||
double add = 1.0f / scale;
|
|
||||||
int offsetX = (int) ((mWidth >> 1) * add);
|
|
||||||
int offsetY = (int) ((mHeight >> 1) * add);
|
|
||||||
|
|
||||||
long pixelRight = x + offsetX;
|
|
||||||
long pixelBottom = y + offsetY;
|
|
||||||
long pixelLeft = x - offsetX;
|
|
||||||
long pixelTop = y - offsetY;
|
|
||||||
|
|
||||||
int tileLeft = MercatorProjection.pixelXToTileX(pixelLeft, zoomLevel);
|
|
||||||
int tileTop = MercatorProjection.pixelYToTileY(pixelTop, zoomLevel);
|
|
||||||
int tileRight = MercatorProjection.pixelXToTileX(pixelRight, zoomLevel);
|
|
||||||
int tileBottom = MercatorProjection.pixelYToTileY(pixelBottom, zoomLevel);
|
|
||||||
|
|
||||||
mJobList.clear();
|
|
||||||
|
|
||||||
// IMapGenerator mapGenerator = mMapView.getMapGenerator();
|
|
||||||
|
|
||||||
int tiles = 0;
|
|
||||||
for (int tileY = tileTop - 1; tileY <= tileBottom + 1; tileY++) {
|
|
||||||
for (int tileX = tileLeft - 1; tileX <= tileRight + 1; tileX++) {
|
|
||||||
|
|
||||||
// GLMapTile tile = mTiles.get(mTileCacheKey.set(tileX, tileY, zoomLevel));
|
|
||||||
//
|
|
||||||
// if (tile == null) {
|
|
||||||
// tile = new GLMapTile(tileX, tileY, zoomLevel);
|
|
||||||
// TileCacheKey key = new TileCacheKey(mTileCacheKey);
|
|
||||||
// mTiles.put(key, tile);
|
|
||||||
//
|
|
||||||
// mTileCacheKey.set((tileX >> 1), (tileY >> 1), (byte) (zoomLevel - 1));
|
|
||||||
// tile.parent = mTiles.get(mTileCacheKey);
|
|
||||||
//
|
|
||||||
// long xx = tileX << 1;
|
|
||||||
// long yy = tileY << 1;
|
|
||||||
// byte z = (byte) (zoomLevel + 1);
|
|
||||||
//
|
|
||||||
// tile.child[0] = mTiles.get(mTileCacheKey.set(xx, yy, z));
|
|
||||||
// tile.child[1] = mTiles.get(mTileCacheKey.set(xx + 1, yy, z));
|
|
||||||
// tile.child[2] = mTiles.get(mTileCacheKey.set(xx, yy + 1, z));
|
|
||||||
// tile.child[3] = mTiles.get(mTileCacheKey.set(xx + 1, yy + 1, z));
|
|
||||||
//
|
|
||||||
// mTileList.add(tile);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// newTiles[tiles++] = tile;
|
|
||||||
//
|
|
||||||
// if (!tile.isReady || (tile.getScale() != scale)) {
|
|
||||||
// // tile.isLoading = true;
|
|
||||||
// // approximation for TileScheduler
|
|
||||||
// if (tileY < tileTop || tileY > tileBottom || tileX < tileLeft
|
|
||||||
// || tileX > tileRight)
|
|
||||||
// tile.isVisible = false;
|
|
||||||
// else
|
|
||||||
// tile.isVisible = true;
|
|
||||||
//
|
|
||||||
// MapGeneratorJob job = new MapGeneratorJob(tile, mJobParameter,
|
|
||||||
// mDebugSettings);
|
|
||||||
// job.setScale(scale);
|
|
||||||
// mJobList.add(job);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (this) {
|
|
||||||
|
|
||||||
limitCache(zoomLevel, (mTileList.size() - 200));
|
|
||||||
|
|
||||||
for (int i = 0; i < tiles; i++)
|
|
||||||
currentTiles[i] = newTiles[i];
|
|
||||||
currentTileCnt = tiles;
|
|
||||||
|
|
||||||
mDrawX = x;
|
|
||||||
mDrawY = y;
|
|
||||||
mMapScale = scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (mJobList.size() > 0) {
|
|
||||||
// mMapView.addJobs(mJobList);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public synchronized void updateMap(boolean clear) {
|
|
||||||
|
|
||||||
boolean update = false;
|
|
||||||
|
|
||||||
mMapPosition = mMapView.getMapPosition().getMapPosition();
|
|
||||||
|
|
||||||
long x = (long) MercatorProjection.longitudeToPixelX(mMapPosition);
|
|
||||||
long y = (long) MercatorProjection.latitudeToPixelY(mMapPosition);
|
|
||||||
|
|
||||||
long tileX = MercatorProjection.pixelXToTileX(x, mMapPosition.zoomLevel);
|
|
||||||
long tileY = MercatorProjection.pixelYToTileY(y, mMapPosition.zoomLevel);
|
|
||||||
float scale = mMapPosition.scale;
|
|
||||||
|
|
||||||
if (mInitial) {
|
|
||||||
mInitial = false;
|
|
||||||
mPrevMapPosition = mMapPosition;
|
|
||||||
mTileX = tileX;
|
|
||||||
mTileY = tileY;
|
|
||||||
update = true;
|
|
||||||
} else if (mPrevMapPosition.zoomLevel != mMapPosition.zoomLevel) {
|
|
||||||
update = true;
|
|
||||||
} else if (mMapScale != scale) {
|
|
||||||
update = true;
|
|
||||||
} else if (tileX != mTileX || tileY != mTileY) {
|
|
||||||
update = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
mTileX = tileX;
|
|
||||||
mTileY = tileY;
|
|
||||||
|
|
||||||
if (update) {
|
|
||||||
// do not change list while drawing
|
|
||||||
// synchronized (this) {
|
|
||||||
mPrevMapPosition = mMapPosition;
|
|
||||||
updateVisibleList(x, y, mMapPosition.zoomLevel);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
synchronized (this) {
|
|
||||||
mDrawX = x;
|
|
||||||
mDrawY = y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mMapView.requestRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
// private MapGeneratorJob mMapGeneratorJob = null;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean passTile(JobTile jobTile) {
|
|
||||||
|
|
||||||
// mMapGeneratorJob = mapGeneratorJob;
|
|
||||||
processedTile = false;
|
|
||||||
mMapView.requestRender();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean drawTile(MapTile tile, int level, float height) {
|
|
||||||
|
|
||||||
// do not recurse more than two parents
|
|
||||||
if (level > 2)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!tile.hasTexture()) {
|
|
||||||
// draw parent below current zoom level tiles
|
|
||||||
float h = height > 0 ? height * 2 : 0.1f;
|
|
||||||
|
|
||||||
if (level <= 2 && tile.parent != null)
|
|
||||||
return drawTile(tile.parent, level + 1, h);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
float z = 1;
|
|
||||||
double drawX = mDrawX;
|
|
||||||
double drawY = mDrawY;
|
|
||||||
// translate all pixel coordinates * 'zoom factor difference'
|
|
||||||
// TODO clip tile when drawing parent
|
|
||||||
int diff = tile.zoomLevel - mMapPosition.zoomLevel;
|
|
||||||
if (diff != 0) {
|
|
||||||
if (diff > 0) {
|
|
||||||
z = (1 << diff);
|
|
||||||
} else {
|
|
||||||
z = 1.0f / (1 << -diff);
|
|
||||||
}
|
|
||||||
// drawX = MercatorProjection
|
|
||||||
// .longitudeToPixelX(mMapPosition.geoPoint.getLongitude(),
|
|
||||||
// tile.zoomLevel);
|
|
||||||
// drawY = MercatorProjection
|
|
||||||
// .latitudeToPixelY(mMapPosition.geoPoint.getLatitude(), tile.zoomLevel);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
float mapScale = mMapScale / z;
|
|
||||||
int tileSize = Tile.TILE_SIZE;
|
|
||||||
float size = tileSize * mapScale;
|
|
||||||
|
|
||||||
float x = (float) ((tile.pixelX) - drawX) * mapScale;
|
|
||||||
float y = (float) ((tile.pixelY + tileSize) - drawY) * mapScale;
|
|
||||||
|
|
||||||
if (x + size < -mWidth / 2 || x > mWidth / 2) {
|
|
||||||
// Log.i(TAG, tile + " skip X " + x + " " + y);
|
|
||||||
tile.isVisible = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (y < -mHeight / 2 || y - size > mHeight / 2) {
|
|
||||||
// Log.i(TAG, tile + " skip Y " + x + " " + y);
|
|
||||||
tile.isVisible = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log.i(TAG, tile + " draw " + x + " " + y);
|
|
||||||
tile.isVisible = true;
|
|
||||||
|
|
||||||
// set drawn tile scale (texture size)
|
|
||||||
GLES20.glUniform1f(muScaleHandle, tile.getScale());
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
// scale tile
|
|
||||||
Matrix.scaleM(mMatrix, 0, mapScale / z, mapScale / z, 1);
|
|
||||||
|
|
||||||
// translate tile
|
|
||||||
Matrix.translateM(mMatrix, 0, (x / size), -(y / size), height);
|
|
||||||
|
|
||||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tile.getTexture());
|
|
||||||
// GlUtils.checkGlError("glBindTexture");
|
|
||||||
|
|
||||||
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMatrix, 0);
|
|
||||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDrawFrame(GL10 glUnused) {
|
|
||||||
// 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);
|
|
||||||
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
GLES20.glUseProgram(mProgram);
|
|
||||||
GlUtils.checkGlError("glUseProgram");
|
|
||||||
|
|
||||||
mVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
|
|
||||||
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
|
|
||||||
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mVertices);
|
|
||||||
GlUtils.checkGlError("glVertexAttribPointer maPosition");
|
|
||||||
|
|
||||||
GLES20.glEnableVertexAttribArray(maPositionHandle);
|
|
||||||
GlUtils.checkGlError("glEnableVertexAttribArray maPositionHandle");
|
|
||||||
|
|
||||||
mVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
|
|
||||||
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,
|
|
||||||
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mVertices);
|
|
||||||
GlUtils.checkGlError("glVertexAttribPointer maTextureHandle");
|
|
||||||
|
|
||||||
GLES20.glEnableVertexAttribArray(maTextureHandle);
|
|
||||||
GlUtils.checkGlError("glEnableVertexAttribArray maTextureHandle");
|
|
||||||
|
|
||||||
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
|
||||||
|
|
||||||
MapTile tile, child, child2;
|
|
||||||
|
|
||||||
GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
|
|
||||||
|
|
||||||
// lock position and currentTiles while drawing
|
|
||||||
// synchronized (this) {
|
|
||||||
// if (mMapGeneratorJob != null) {
|
|
||||||
//
|
|
||||||
// tile = (GLMapTile) mMapGeneratorJob.tile;
|
|
||||||
// // TODO tile bitmaps texture to smaller parts avoiding uploading full
|
|
||||||
// // bitmap when not necessary
|
|
||||||
// if (tile.getTexture() >= 0) {
|
|
||||||
// // reuse tile texture
|
|
||||||
// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tile.getTexture());
|
|
||||||
// GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
|
|
||||||
// mMapGeneratorJob.getBitmap());
|
|
||||||
// } else if (mTextures.size() > 0) {
|
|
||||||
// // reuse texture from previous tiles
|
|
||||||
// Integer texture;
|
|
||||||
// texture = mTextures.remove(mTextures.size() - 1);
|
|
||||||
//
|
|
||||||
// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture.intValue());
|
|
||||||
// GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
|
|
||||||
// mMapGeneratorJob.getBitmap());
|
|
||||||
// tile.setTexture(texture.intValue());
|
|
||||||
// } else {
|
|
||||||
// // create texture
|
|
||||||
// tile.setTexture(GlUtils.loadTextures(mMapGeneratorJob.getBitmap()));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// tile.setScale(mMapGeneratorJob.getScale());
|
|
||||||
// tile.isReady = true;
|
|
||||||
// tile.isLoading = false;
|
|
||||||
//
|
|
||||||
// mMapGeneratorJob = null;
|
|
||||||
// processedTile = true;
|
|
||||||
// // loadedTexture = true;
|
|
||||||
// }
|
|
||||||
// int tileSize = (int) (Tile.TILE_SIZE * mMapScale);
|
|
||||||
// int hWidth = mWidth >> 1;
|
|
||||||
// int hHeight = mHeight >> 1;
|
|
||||||
// for (int i = 0, n = currentTileCnt; i < n; i++) {
|
|
||||||
// tile = currentTiles[i];
|
|
||||||
//
|
|
||||||
// float x = (float) (tile.pixelX - mDrawX);
|
|
||||||
// float y = (float) (tile.pixelY - mDrawY);
|
|
||||||
//
|
|
||||||
// // clip rendering to tile boundaries
|
|
||||||
// GLES20.glScissor(
|
|
||||||
// hWidth + (int) (x * mMapScale) - 2,
|
|
||||||
// hHeight - (int) (y * mMapScale) - tileSize - 2,
|
|
||||||
// tileSize + 4, tileSize + 4);
|
|
||||||
//
|
|
||||||
// if (drawTile(tile, 0, 0.0f))
|
|
||||||
// continue;
|
|
||||||
//
|
|
||||||
// // or two zoom level above
|
|
||||||
// for (int k = 0; k < 4; k++) {
|
|
||||||
// if (((child = tile.child[k]) != null)) {
|
|
||||||
//
|
|
||||||
// if (drawTile(child, 2, 0.1f))
|
|
||||||
// continue;
|
|
||||||
//
|
|
||||||
// for (int j = 0; j < 4; j++)
|
|
||||||
// if ((child2 = child.child[j]) != null)
|
|
||||||
// drawTile(child2, 2, 0.1f);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
|
|
||||||
mWidth = width;
|
|
||||||
mHeight = height;
|
|
||||||
|
|
||||||
int tiles = (mWidth / Tile.TILE_SIZE + 4) * (mHeight / Tile.TILE_SIZE + 4);
|
|
||||||
currentTiles = new MapTile[tiles];
|
|
||||||
newTiles = new MapTile[tiles];
|
|
||||||
|
|
||||||
GLES20.glViewport(0, 0, width, height);
|
|
||||||
|
|
||||||
// mDebugSettings = mMapView.getDebugSettings();
|
|
||||||
// mJobParameter = mMapView.getJobParameters();
|
|
||||||
|
|
||||||
// mTiles.clear();
|
|
||||||
mTileList.clear();
|
|
||||||
mTextures.clear();
|
|
||||||
mInitial = true;
|
|
||||||
mMapView.redrawTiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
|
|
||||||
|
|
||||||
mProgram = GlUtils.createProgram(mVertexShader, mFragmentShader);
|
|
||||||
if (mProgram == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
|
|
||||||
GlUtils.checkGlError("glGetAttribLocation aPosition");
|
|
||||||
if (maPositionHandle == -1) {
|
|
||||||
throw new RuntimeException("Could not get attrib location for aPosition");
|
|
||||||
}
|
|
||||||
maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
|
|
||||||
GlUtils.checkGlError("glGetAttribLocation aTextureCoord");
|
|
||||||
if (maTextureHandle == -1) {
|
|
||||||
throw new RuntimeException("Could not get attrib location for aTextureCoord");
|
|
||||||
}
|
|
||||||
muScaleHandle = GLES20.glGetUniformLocation(mProgram, "uScale");
|
|
||||||
GlUtils.checkGlError("glGetAttribLocation uScale");
|
|
||||||
if (muScaleHandle == -1) {
|
|
||||||
throw new RuntimeException("Could not get attrib location for uScale");
|
|
||||||
}
|
|
||||||
|
|
||||||
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
|
|
||||||
GlUtils.checkGlError("glGetUniformLocation uMVPMatrix");
|
|
||||||
if (muMVPMatrixHandle == -1) {
|
|
||||||
throw new RuntimeException("Could not get attrib location for uMVPMatrix");
|
|
||||||
}
|
|
||||||
|
|
||||||
// GLES20.glEnable(GLES20.GL_DEPTH_TEST);
|
|
||||||
// GLES20.glDepthFunc(GLES20.GL_LEQUAL);
|
|
||||||
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
|
|
||||||
|
|
||||||
GLES20.glCullFace(GLES20.GL_BACK);
|
|
||||||
GLES20.glFrontFace(GLES20.GL_CW);
|
|
||||||
GLES20.glEnable(GLES20.GL_CULL_FACE);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String mVertexShader = "precision highp float;\n" +
|
|
||||||
"uniform float uScale;\n" +
|
|
||||||
"uniform mat4 uMVPMatrix;\n" + "attribute vec4 aPosition;\n" +
|
|
||||||
"attribute vec2 aTextureCoord;\n" +
|
|
||||||
"varying vec2 vTextureCoord;\n" + "void main() {\n" +
|
|
||||||
" gl_Position = uMVPMatrix * aPosition;\n" +
|
|
||||||
" vTextureCoord = aTextureCoord * uScale;\n" +
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
private final String mFragmentShader = "precision highp float;\n" +
|
|
||||||
"uniform float uScale;\n" +
|
|
||||||
"varying vec2 vTextureCoord;\n" +
|
|
||||||
"uniform sampler2D sTexture;\n" +
|
|
||||||
"void main() {\n" +
|
|
||||||
" gl_FragColor = texture2D(sTexture, vTextureCoord); \n" +
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public boolean processedTile() {
|
|
||||||
// return processedTile;
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IMapGenerator createMapGenerator() {
|
|
||||||
return new MapGenerator(mMapView);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRenderTheme(RenderTheme t) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
import org.oscim.view.mapgenerator.JobTile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class MapTile extends JobTile {
|
|
||||||
private float mScale;
|
|
||||||
|
|
||||||
final MapTile[] child = { null, null, null, null };
|
|
||||||
MapTile parent;
|
|
||||||
|
|
||||||
// private long mLoadTime;
|
|
||||||
private int mTextureID;
|
|
||||||
|
|
||||||
boolean isVisible;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param tileX
|
|
||||||
* ...
|
|
||||||
* @param tileY
|
|
||||||
* ...
|
|
||||||
* @param zoomLevel
|
|
||||||
* ..
|
|
||||||
*/
|
|
||||||
public MapTile(int tileX, int tileY, byte zoomLevel) {
|
|
||||||
super(tileX, tileY, zoomLevel);
|
|
||||||
mScale = 1;
|
|
||||||
mTextureID = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return ...
|
|
||||||
*/
|
|
||||||
public int getTexture() {
|
|
||||||
return mTextureID;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mTextureID
|
|
||||||
* ...
|
|
||||||
*/
|
|
||||||
public void setTexture(int mTextureID) {
|
|
||||||
this.mTextureID = mTextureID;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return ...
|
|
||||||
*/
|
|
||||||
public boolean hasTexture() {
|
|
||||||
return mTextureID >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return ...
|
|
||||||
*/
|
|
||||||
public float getScale() {
|
|
||||||
return mScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param scale
|
|
||||||
* ...
|
|
||||||
*/
|
|
||||||
public void setScale(float scale) {
|
|
||||||
mScale = scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.Rect;
|
|
||||||
|
|
||||||
class PointTextContainer {
|
|
||||||
final Rect boundary;
|
|
||||||
final Paint paintBack;
|
|
||||||
final Paint paintFront;
|
|
||||||
SymbolContainer symbol;
|
|
||||||
final String text;
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new point container, that holds the x-y coordinates of a point, a text variable and one paint objects.
|
|
||||||
*
|
|
||||||
* @param text
|
|
||||||
* the text of the point.
|
|
||||||
* @param x
|
|
||||||
* the x coordinate of the point.
|
|
||||||
* @param y
|
|
||||||
* the y coordinate of the point.
|
|
||||||
* @param paintFront
|
|
||||||
* the paintFront for the point.
|
|
||||||
*/
|
|
||||||
PointTextContainer(String text, float x, float y, Paint paintFront) {
|
|
||||||
this.text = text;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.paintFront = paintFront;
|
|
||||||
this.paintBack = null;
|
|
||||||
this.symbol = null;
|
|
||||||
|
|
||||||
this.boundary = new Rect();
|
|
||||||
paintFront.getTextBounds(text, 0, text.length(), this.boundary);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new point container, that holds the x-y coordinates of a point, a text variable and two paint objects.
|
|
||||||
*
|
|
||||||
* @param text
|
|
||||||
* the text of the point.
|
|
||||||
* @param x
|
|
||||||
* the x coordinate of the point.
|
|
||||||
* @param y
|
|
||||||
* the y coordinate of the point.
|
|
||||||
* @param paintFront
|
|
||||||
* the paintFront for the point.
|
|
||||||
* @param paintBack
|
|
||||||
* the paintBack for the point.
|
|
||||||
*/
|
|
||||||
PointTextContainer(String text, float x, float y, Paint paintFront, Paint paintBack) {
|
|
||||||
this.text = text;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.paintFront = paintFront;
|
|
||||||
this.paintBack = paintBack;
|
|
||||||
this.symbol = null;
|
|
||||||
|
|
||||||
this.boundary = new Rect();
|
|
||||||
if (paintBack != null) {
|
|
||||||
paintBack.getTextBounds(text, 0, text.length(), this.boundary);
|
|
||||||
} else {
|
|
||||||
paintFront.getTextBounds(text, 0, text.length(), this.boundary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new point container, that holds the x-y coordinates of a point, a text variable, two paint objects, and
|
|
||||||
* a reference on a symbol, if the text is connected with a POI.
|
|
||||||
*
|
|
||||||
* @param text
|
|
||||||
* the text of the point.
|
|
||||||
* @param x
|
|
||||||
* the x coordinate of the point.
|
|
||||||
* @param y
|
|
||||||
* the y coordinate of the point.
|
|
||||||
* @param paintFront
|
|
||||||
* the paintFront for the point.
|
|
||||||
* @param paintBack
|
|
||||||
* the paintBack for the point.
|
|
||||||
* @param symbol
|
|
||||||
* the connected Symbol.
|
|
||||||
*/
|
|
||||||
PointTextContainer(String text, float x, float y, Paint paintFront, Paint paintBack, SymbolContainer symbol) {
|
|
||||||
this.text = text;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.paintFront = paintFront;
|
|
||||||
this.paintBack = paintBack;
|
|
||||||
this.symbol = symbol;
|
|
||||||
|
|
||||||
this.boundary = new Rect();
|
|
||||||
if (paintBack != null) {
|
|
||||||
paintBack.getTextBounds(text, 0, text.length(), this.boundary);
|
|
||||||
} else {
|
|
||||||
paintFront.getTextBounds(text, 0, text.length(), this.boundary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
interface ShapeContainer {
|
|
||||||
ShapeType getShapeType();
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
|
|
||||||
import android.graphics.Paint;
|
|
||||||
|
|
||||||
class ShapePaintContainer {
|
|
||||||
public Paint paint;
|
|
||||||
public ShapeContainer shapeContainer;
|
|
||||||
public ShapePaintContainer next;
|
|
||||||
|
|
||||||
ShapePaintContainer(ShapeContainer shapeContainer, Paint paint) {
|
|
||||||
this.shapeContainer = shapeContainer;
|
|
||||||
this.paint = paint;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
|
|
||||||
class SymbolContainer {
|
|
||||||
final boolean alignCenter;
|
|
||||||
final float rotation;
|
|
||||||
final Bitmap symbol;
|
|
||||||
final float x;
|
|
||||||
final float y;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new symbol container. The symbol will not be centered.
|
|
||||||
*
|
|
||||||
* @param symbol
|
|
||||||
* the symbol to render at the point
|
|
||||||
* @param x
|
|
||||||
* the x coordinate of the point.
|
|
||||||
* @param y
|
|
||||||
* the y coordinate of the point.
|
|
||||||
*/
|
|
||||||
SymbolContainer(Bitmap symbol, float x, float y) {
|
|
||||||
this(symbol, x, y, false, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new symbol container.
|
|
||||||
*
|
|
||||||
* @param symbol
|
|
||||||
* the symbol to render at the point
|
|
||||||
* @param x
|
|
||||||
* the x coordinate of the point.
|
|
||||||
* @param y
|
|
||||||
* the y coordinate of the point.
|
|
||||||
* @param alignCenter
|
|
||||||
* true if the symbol should be centered, false otherwise.
|
|
||||||
* @param rotation
|
|
||||||
* the rotation of the symbol.
|
|
||||||
*/
|
|
||||||
SymbolContainer(Bitmap symbol, float x, float y, boolean alignCenter, float rotation) {
|
|
||||||
this.symbol = symbol;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.alignCenter = alignCenter;
|
|
||||||
this.rotation = rotation;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
class WayDataContainer implements ShapeContainer {
|
|
||||||
// position and length of float coordinates
|
|
||||||
|
|
||||||
int[] position;
|
|
||||||
int[] length;
|
|
||||||
|
|
||||||
int[] textPos;
|
|
||||||
|
|
||||||
WayDataContainer(int size) {
|
|
||||||
length = new int[size];
|
|
||||||
position = new int[size];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ShapeType getShapeType() {
|
|
||||||
return ShapeType.WAY;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,300 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.oscim.view.utils.GeometryUtils;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
final class WayDecorator {
|
|
||||||
/**
|
|
||||||
* Minimum distance in pixels before the symbol is repeated.
|
|
||||||
*/
|
|
||||||
private static final int DISTANCE_BETWEEN_SYMBOLS = 200;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimum distance in pixels before the way name is repeated.
|
|
||||||
*/
|
|
||||||
private static final int DISTANCE_BETWEEN_WAY_NAMES = 500;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Distance in pixels to skip from both ends of a segment.
|
|
||||||
*/
|
|
||||||
private static final int SEGMENT_SAFETY_DISTANCE = 30;
|
|
||||||
|
|
||||||
static void renderSymbol(Bitmap symbolBitmap, boolean alignCenter,
|
|
||||||
boolean repeatSymbol, float[][] coordinates,
|
|
||||||
List<SymbolContainer> waySymbols) {
|
|
||||||
int skipPixels = SEGMENT_SAFETY_DISTANCE;
|
|
||||||
|
|
||||||
// get the first way point coordinates
|
|
||||||
float previousX = coordinates[0][0];
|
|
||||||
float previousY = coordinates[0][1];
|
|
||||||
|
|
||||||
// draw the symbol on each way segment
|
|
||||||
float segmentLengthRemaining;
|
|
||||||
float segmentSkipPercentage;
|
|
||||||
float symbolAngle;
|
|
||||||
for (int i = 2; i < coordinates[0].length; i += 2) {
|
|
||||||
// get the current way point coordinates
|
|
||||||
float currentX = coordinates[0][i];
|
|
||||||
float currentY = coordinates[0][i + 1];
|
|
||||||
|
|
||||||
// calculate the length of the current segment (Euclidian distance)
|
|
||||||
float diffX = currentX - previousX;
|
|
||||||
float diffY = currentY - previousY;
|
|
||||||
double segmentLengthInPixel = Math.sqrt(diffX * diffX + diffY * diffY);
|
|
||||||
segmentLengthRemaining = (float) segmentLengthInPixel;
|
|
||||||
|
|
||||||
while (segmentLengthRemaining - skipPixels > SEGMENT_SAFETY_DISTANCE) {
|
|
||||||
// calculate the percentage of the current segment to skip
|
|
||||||
segmentSkipPercentage = skipPixels / segmentLengthRemaining;
|
|
||||||
|
|
||||||
// move the previous point forward towards the current point
|
|
||||||
previousX += diffX * segmentSkipPercentage;
|
|
||||||
previousY += diffY * segmentSkipPercentage;
|
|
||||||
symbolAngle = (float) Math.toDegrees(Math.atan2(currentY - previousY,
|
|
||||||
currentX - previousX));
|
|
||||||
|
|
||||||
waySymbols.add(new SymbolContainer(symbolBitmap, previousX, previousY,
|
|
||||||
alignCenter, symbolAngle));
|
|
||||||
|
|
||||||
// check if the symbol should only be rendered once
|
|
||||||
if (!repeatSymbol) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// recalculate the distances
|
|
||||||
diffX = currentX - previousX;
|
|
||||||
diffY = currentY - previousY;
|
|
||||||
|
|
||||||
// recalculate the remaining length of the current segment
|
|
||||||
segmentLengthRemaining -= skipPixels;
|
|
||||||
|
|
||||||
// set the amount of pixels to skip before repeating the symbol
|
|
||||||
skipPixels = DISTANCE_BETWEEN_SYMBOLS;
|
|
||||||
}
|
|
||||||
|
|
||||||
skipPixels -= segmentLengthRemaining;
|
|
||||||
if (skipPixels < SEGMENT_SAFETY_DISTANCE) {
|
|
||||||
skipPixels = SEGMENT_SAFETY_DISTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the previous way point coordinates for the next loop
|
|
||||||
previousX = currentX;
|
|
||||||
previousY = currentY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void renderText(MapGenerator mapGenerator, Paint paint, Paint outline,
|
|
||||||
float[] coordinates, WayDataContainer wayDataContainer,
|
|
||||||
List<WayTextContainer> wayNames) {
|
|
||||||
|
|
||||||
int pos = wayDataContainer.position[0];
|
|
||||||
int len = wayDataContainer.length[0];
|
|
||||||
// int coordinatesLength
|
|
||||||
|
|
||||||
String text = null;
|
|
||||||
// calculate the way name length plus some margin of safety
|
|
||||||
float wayNameWidth = -1; // paint.measureText(textKey) + 5;
|
|
||||||
float minWidth = 100;
|
|
||||||
int skipPixels = 0;
|
|
||||||
|
|
||||||
// get the first way point coordinates
|
|
||||||
int previousX = (int) coordinates[pos + 0];
|
|
||||||
int previousY = (int) coordinates[pos + 1];
|
|
||||||
int containerSize = -1;
|
|
||||||
|
|
||||||
// find way segments long enough to draw the way name on them
|
|
||||||
for (int i = pos + 2; i < pos + len; i += 2) {
|
|
||||||
// get the current way point coordinates
|
|
||||||
int currentX = (int) coordinates[i];
|
|
||||||
int currentY = (int) coordinates[i + 1];
|
|
||||||
int first = i - 2;
|
|
||||||
int last = i;
|
|
||||||
|
|
||||||
// calculate the length of the current segment (Euclidian distance)
|
|
||||||
int diffX = currentX - previousX;
|
|
||||||
int diffY = currentY - previousY;
|
|
||||||
|
|
||||||
for (int j = i + 2; j < pos + len; j += 2) {
|
|
||||||
int nextX = (int) coordinates[j];
|
|
||||||
int nextY = (int) coordinates[j + 1];
|
|
||||||
|
|
||||||
if (diffY == 0) {
|
|
||||||
if ((currentY - nextY) != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
currentX = nextX;
|
|
||||||
currentY = nextY;
|
|
||||||
last = j;
|
|
||||||
continue;
|
|
||||||
} else if ((currentY - nextY) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
float diff = ((float) (diffX) / (diffY) - (float) (currentX - nextX)
|
|
||||||
/ (currentY - nextY));
|
|
||||||
|
|
||||||
// skip segments with corners
|
|
||||||
if (diff >= 0.2 || diff <= -0.2)
|
|
||||||
break;
|
|
||||||
|
|
||||||
currentX = nextX;
|
|
||||||
currentY = nextY;
|
|
||||||
last = j;
|
|
||||||
}
|
|
||||||
|
|
||||||
diffX = currentX - previousX;
|
|
||||||
diffY = currentY - previousY;
|
|
||||||
|
|
||||||
if (diffX < 0)
|
|
||||||
diffX = -diffX;
|
|
||||||
if (diffY < 0)
|
|
||||||
diffY = -diffY;
|
|
||||||
|
|
||||||
if (diffX + diffY < minWidth) {
|
|
||||||
previousX = currentX;
|
|
||||||
previousY = currentY;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wayNameWidth > 0 && diffX + diffY < wayNameWidth) {
|
|
||||||
previousX = currentX;
|
|
||||||
previousY = currentY;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
double segmentLengthInPixel = Math.sqrt(diffX * diffX + diffY * diffY);
|
|
||||||
|
|
||||||
if (skipPixels > 0) {
|
|
||||||
skipPixels -= segmentLengthInPixel;
|
|
||||||
|
|
||||||
} else if (segmentLengthInPixel > minWidth) {
|
|
||||||
|
|
||||||
if (wayNameWidth < 0) {
|
|
||||||
if (text == null) {
|
|
||||||
// text = mapGenerator.getWayName();
|
|
||||||
// if (text == null)
|
|
||||||
text = "blub";
|
|
||||||
}
|
|
||||||
|
|
||||||
wayNameWidth = (paint.measureText(text) + 10);
|
|
||||||
}
|
|
||||||
if (segmentLengthInPixel > wayNameWidth) {
|
|
||||||
|
|
||||||
double s = (wayNameWidth + 10) / segmentLengthInPixel;
|
|
||||||
int width, height;
|
|
||||||
int x1, y1, x2, y2;
|
|
||||||
|
|
||||||
if (previousX < currentX) {
|
|
||||||
x1 = previousX;
|
|
||||||
y1 = previousY;
|
|
||||||
x2 = currentX;
|
|
||||||
y2 = currentY;
|
|
||||||
} else {
|
|
||||||
x1 = currentX;
|
|
||||||
y1 = currentY;
|
|
||||||
x2 = previousX;
|
|
||||||
y2 = previousY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// estimate position of text on path
|
|
||||||
width = (x2 - x1) / 2;
|
|
||||||
x2 = x2 - (int) (width - s * width);
|
|
||||||
x1 = x1 + (int) (width - s * width);
|
|
||||||
|
|
||||||
height = (y2 - y1) / 2;
|
|
||||||
y2 = y2 - (int) (height - s * height);
|
|
||||||
y1 = y1 + (int) (height - s * height);
|
|
||||||
|
|
||||||
short top = (short) (y1 < y2 ? y1 : y2);
|
|
||||||
short bot = (short) (y1 < y2 ? y2 : y1);
|
|
||||||
|
|
||||||
boolean intersects = false;
|
|
||||||
|
|
||||||
if (containerSize == -1)
|
|
||||||
containerSize = wayNames.size();
|
|
||||||
|
|
||||||
for (int k = 0; k < containerSize; k++) {
|
|
||||||
WayTextContainer wtc2 = wayNames.get(k);
|
|
||||||
if (!wtc2.match)
|
|
||||||
// outline (not 'match') are appended to the end;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// check crossings
|
|
||||||
if (GeometryUtils.lineIntersect(x1, y1, x2, y2, wtc2.x1, wtc2.y1,
|
|
||||||
wtc2.x2, wtc2.y2)) {
|
|
||||||
intersects = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check overlapping labels of road with more than one
|
|
||||||
// way
|
|
||||||
short top2 = (wtc2.y1 < wtc2.y2 ? wtc2.y1 : wtc2.y2);
|
|
||||||
short bot2 = (wtc2.y1 < wtc2.y2 ? wtc2.y2 : wtc2.y1);
|
|
||||||
|
|
||||||
if (x1 - 10 < wtc2.x2 && wtc2.x1 - 10 < x2 && top - 10 < bot2
|
|
||||||
&& top2 - 10 < bot) {
|
|
||||||
|
|
||||||
if (wtc2.text.equals(text)) {
|
|
||||||
intersects = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intersects) {
|
|
||||||
previousX = (int) coordinates[pos + i];
|
|
||||||
previousY = (int) coordinates[pos + i + 1];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d("mapsforge", "add " + text + " " + first + " " + last);
|
|
||||||
WayTextContainer wtc = new WayTextContainer(first, last,
|
|
||||||
wayDataContainer, text,
|
|
||||||
paint);
|
|
||||||
wtc.x1 = (short) x1;
|
|
||||||
wtc.y1 = (short) y1;
|
|
||||||
wtc.x2 = (short) x2;
|
|
||||||
wtc.y2 = (short) y2;
|
|
||||||
wtc.match = true;
|
|
||||||
|
|
||||||
wayNames.add(0, wtc);
|
|
||||||
containerSize++;
|
|
||||||
|
|
||||||
if (outline != null) {
|
|
||||||
wayNames.add(new WayTextContainer(first, last, wayDataContainer,
|
|
||||||
text, outline));
|
|
||||||
containerSize++;
|
|
||||||
}
|
|
||||||
// 500 ??? how big is a tile?!
|
|
||||||
skipPixels = DISTANCE_BETWEEN_WAY_NAMES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// store the previous way point coordinates
|
|
||||||
previousX = currentX;
|
|
||||||
previousY = currentY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private WayDecorator() {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.view.swrenderer;
|
|
||||||
|
|
||||||
|
|
||||||
import android.graphics.Paint;
|
|
||||||
|
|
||||||
class WayTextContainer {
|
|
||||||
final WayDataContainer wayDataContainer;
|
|
||||||
final int first;
|
|
||||||
final int last;
|
|
||||||
final Paint paint;
|
|
||||||
final String text;
|
|
||||||
short x1, y1, x2, y2;
|
|
||||||
boolean match;
|
|
||||||
|
|
||||||
WayTextContainer(int first, int last, WayDataContainer wayDataContainer, String text, Paint paint) {
|
|
||||||
this.wayDataContainer = wayDataContainer;
|
|
||||||
this.first = first;
|
|
||||||
this.last = last;
|
|
||||||
this.text = text;
|
|
||||||
this.paint = paint;
|
|
||||||
this.match = false;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user