implement osm bugs layer
git-svn-id: https://osmand.googlecode.com/svn/trunk@139 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
parent
c0efd98ff6
commit
c6e16ea747
11 changed files with 334 additions and 12 deletions
|
@ -11,7 +11,7 @@ public class ToDoConstants {
|
|||
*/
|
||||
public int DESCRIBE_ABOUT_AUTHORS = 8;
|
||||
|
||||
// TODO ANDROID NOT in release 0.1
|
||||
// TODO ANDROID
|
||||
// 8. Enable change POI directly on map (requires OSM login)
|
||||
// 16. Support open street bugs api.
|
||||
// 20. Implement save track/route to gpx (?)
|
||||
|
@ -23,13 +23,12 @@ public class ToDoConstants {
|
|||
// 32. Introduce POI predefined filters (car filter(other-fuel, transportation-car_wash, show-car) and others)
|
||||
// 33. Build transport locations (investigate)
|
||||
// 34. Investigate routing (bicycle, car)
|
||||
// 35. Enable trackball navigation in android
|
||||
|
||||
|
||||
// FIXME Bugs Android :
|
||||
// 10. Notification is gone after clear all notifications (TODO test)
|
||||
|
||||
// TODO swing NOT in release 0.1
|
||||
// TODO swing
|
||||
// 1. Download tiles without using dir tiles
|
||||
// 2. Internal (Simplify MapPanel - introduce layers for it)
|
||||
|
||||
|
||||
// DONE ANDROID :
|
||||
|
|
|
@ -24,7 +24,7 @@ import com.osmand.LogUtil;
|
|||
public class MapTileDownloader {
|
||||
// Application constants
|
||||
public static String APP_NAME = "OsmAnd";
|
||||
public static String APP_VERSION = "0.1";
|
||||
public static String APP_VERSION = "0.2";
|
||||
|
||||
|
||||
// Download manager tile settings
|
||||
|
@ -131,7 +131,15 @@ public class MapTileDownloader {
|
|||
|
||||
|
||||
public void refuseAllPreviousRequests(){
|
||||
threadPoolExecutor.getQueue().clear();
|
||||
//FIXME it could cause NPE in android implementation think abou different style
|
||||
// That's very strange because exception in impl of queue (possibly wrong impl)
|
||||
// threadPoolExecutor.getQueue().clear();
|
||||
while(!threadPoolExecutor.getQueue().isEmpty()){
|
||||
try {
|
||||
threadPoolExecutor.getQueue().take();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void requestToDownload(DownloadRequest request){
|
||||
|
|
|
@ -104,7 +104,9 @@ public class OsmExtractionUI implements IMapLocationListener {
|
|||
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(){
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
if(!(e instanceof ThreadDeath)){
|
||||
log.error("Error in thread " + t.getName(), e);
|
||||
}
|
||||
defaultHandler.uncaughtException(t, e);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="show_osm_bugs_descr">Show open street bugs on map</string>
|
||||
<string name="show_osm_bugs">Show open street bugs</string>
|
||||
<string name="favourites_activity">List of favourite points</string>
|
||||
<string name="add_to_favourite">Add to Favourites</string>
|
||||
<string name="use_english_names_descr">Select use native or english names</string>
|
||||
|
@ -21,7 +23,7 @@
|
|||
<string name="map_view_3d">Map View 3D</string>
|
||||
<string name="rotate_map_to_bearing_descr">Rotate map to bearing of your direction</string>
|
||||
<string name="rotate_map_to_bearing">Rotate map</string>
|
||||
<string name="show_poi_over_map_description">Show POI on map</string>
|
||||
<string name="show_poi_over_map_description">Show POI on map (zoom > 15)</string>
|
||||
<string name="show_poi_over_map">Show POI</string>
|
||||
<string name="map_tile_source_descr">Choose the source of tiles:</string>
|
||||
<string name="map_tile_source">Map tile source</string>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<CheckBoxPreference android:key="show_poi_over_map" android:title="@string/show_poi_over_map" android:summary="@string/show_poi_over_map_description"></CheckBoxPreference>
|
||||
<CheckBoxPreference android:key="rotate_map_to_bearing" android:title="@string/rotate_map_to_bearing" android:summary="@string/rotate_map_to_bearing_descr"></CheckBoxPreference>
|
||||
<CheckBoxPreference android:key="show_view_angle" android:title="@string/show_view_angle" android:summary="@string/show_view_angle_descr"></CheckBoxPreference>
|
||||
|
||||
<CheckBoxPreference android:key="show_osm_bugs" android:title="@string/show_osm_bugs" android:summary="@string/show_osm_bugs_descr"></CheckBoxPreference>
|
||||
<ListPreference android:key="position_on_map" android:title="@string/position_on_map" android:summary="@string/position_on_map_descr"></ListPreference>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/map_source"><ListPreference android:title="@string/map_tile_source" android:summary="@string/map_tile_source_descr" android:key="map_tile_sources"></ListPreference>
|
||||
|
|
|
@ -33,6 +33,14 @@ public class OsmandSettings {
|
|||
return prefs.getBoolean(SHOW_POI_OVER_MAP, false);
|
||||
}
|
||||
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public static final String SHOW_OSM_BUGS = "show_osm_bugs";
|
||||
public static boolean isShowingOsmBugs(Context ctx){
|
||||
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
|
||||
return prefs.getBoolean(SHOW_OSM_BUGS, false);
|
||||
}
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public static final String SHOW_VIEW_ANGLE = "show_view_angle";
|
||||
public static boolean isShowingViewAngle(Context ctx){
|
||||
|
|
|
@ -43,6 +43,7 @@ import com.osmand.data.preparation.MapTileDownloader;
|
|||
import com.osmand.map.IMapLocationListener;
|
||||
import com.osmand.osm.LatLon;
|
||||
import com.osmand.views.MapInfoLayer;
|
||||
import com.osmand.views.OsmBugsLayer;
|
||||
import com.osmand.views.OsmandMapTileView;
|
||||
import com.osmand.views.POIMapLayer;
|
||||
import com.osmand.views.PointLocationLayer;
|
||||
|
@ -61,11 +62,14 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
|
|||
private PointNavigationLayer navigationLayer;
|
||||
private POIMapLayer poiMapLayer;
|
||||
private MapInfoLayer mapInfoLayer;
|
||||
private OsmBugsLayer osmBugsLayer;
|
||||
|
||||
private WakeLock wakeLock;
|
||||
private boolean sensorRegistered = false;
|
||||
private Handler sensorHandler = new Handler();
|
||||
|
||||
|
||||
|
||||
private final static String BACK_TO_LOCATION = "BACK_TO_LOCATION";
|
||||
private final static String POINT_NAVIGATE_LAT = "POINT_NAVIGATE_LAT";
|
||||
private final static String POINT_NAVIGATE_LON = "POINT_NAVIGATE_LON";
|
||||
|
@ -95,6 +99,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
|
|||
mapView.addLayer(locationLayer);
|
||||
mapInfoLayer = new MapInfoLayer(this);
|
||||
mapView.addLayer(mapInfoLayer);
|
||||
osmBugsLayer = new OsmBugsLayer();
|
||||
|
||||
|
||||
|
||||
|
@ -305,6 +310,14 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
|
|||
mapView.removeLayer(poiMapLayer);
|
||||
}
|
||||
}
|
||||
if(mapView.getLayers().contains(osmBugsLayer) != OsmandSettings.isShowingOsmBugs(this)){
|
||||
if(OsmandSettings.isShowingOsmBugs(this)){
|
||||
mapView.addLayer(osmBugsLayer);
|
||||
} else {
|
||||
mapView.removeLayer(osmBugsLayer);
|
||||
}
|
||||
}
|
||||
|
||||
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
|
||||
service.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, this);
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
private CheckBoxPreference showViewAngle;
|
||||
private ListPreference positionOnMap;
|
||||
private CheckBoxPreference useEnglishNames;
|
||||
private CheckBoxPreference showOsmBugs;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -41,6 +42,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
rotateMapToBearing.setOnPreferenceChangeListener(this);
|
||||
showViewAngle =(CheckBoxPreference) screen.findPreference(OsmandSettings.SHOW_VIEW_ANGLE);
|
||||
showViewAngle.setOnPreferenceChangeListener(this);
|
||||
showOsmBugs =(CheckBoxPreference) screen.findPreference(OsmandSettings.SHOW_OSM_BUGS);
|
||||
showOsmBugs.setOnPreferenceChangeListener(this);
|
||||
useEnglishNames =(CheckBoxPreference) screen.findPreference(OsmandSettings.USE_ENGLISH_NAMES);
|
||||
useEnglishNames.setOnPreferenceChangeListener(this);
|
||||
|
||||
|
@ -59,6 +62,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
showPoiOnMap.setChecked(OsmandSettings.isShowingPoiOverMap(this));
|
||||
rotateMapToBearing.setChecked(OsmandSettings.isRotateMapToBearing(this));
|
||||
showViewAngle.setChecked(OsmandSettings.isShowingViewAngle(this));
|
||||
showOsmBugs.setChecked(OsmandSettings.isShowingOsmBugs(this));
|
||||
useEnglishNames.setChecked(OsmandSettings.usingEnglishNames(this));
|
||||
String[] e = new String[] { "Center", "Bottom" };
|
||||
positionOnMap.setEntryValues(e);
|
||||
|
@ -99,6 +103,9 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
} else if(preference == showViewAngle){
|
||||
edit.putBoolean(OsmandSettings.SHOW_VIEW_ANGLE, (Boolean) newValue);
|
||||
edit.commit();
|
||||
} else if(preference == showOsmBugs){
|
||||
edit.putBoolean(OsmandSettings.SHOW_OSM_BUGS, (Boolean) newValue);
|
||||
edit.commit();
|
||||
} else if(preference == positionOnMap){
|
||||
edit.putInt(OsmandSettings.POSITION_ON_MAP, positionOnMap.findIndexOfValue((String) newValue));
|
||||
edit.commit();
|
||||
|
|
278
OsmAnd/src/com/osmand/views/OsmBugsLayer.java
Normal file
278
OsmAnd/src/com/osmand/views/OsmBugsLayer.java
Normal file
|
@ -0,0 +1,278 @@
|
|||
package com.osmand.views;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.osmand.LogUtil;
|
||||
import com.osmand.osm.MapUtils;
|
||||
|
||||
public class OsmBugsLayer implements OsmandMapLayer {
|
||||
|
||||
private static final Log log = LogUtil.getLog(OsmBugsLayer.class);
|
||||
private final static int startZoom = 8;
|
||||
private final int SEARCH_LIMIT = 100;
|
||||
|
||||
private OsmandMapTileView view;
|
||||
private Handler handlerToLoop;
|
||||
private Rect pixRect = new Rect();
|
||||
private RectF tileRect = new RectF();
|
||||
|
||||
private List<OpenStreetBug> objects = new ArrayList<OpenStreetBug>();
|
||||
private Paint pointClosedUI;
|
||||
private Paint pointOpenedUI;
|
||||
private Pattern patternToParse = Pattern.compile("putAJAXMarker\\((\\d*), ((\\d|\\.)*), ((\\d|\\.)*), '([^']*)', (\\d)\\);");
|
||||
|
||||
private double cTopLatitude;
|
||||
private double cBottomLatitude;
|
||||
private double cLeftLongitude;
|
||||
private double cRightLongitude;
|
||||
private int czoom;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void initLayer(OsmandMapTileView view) {
|
||||
this.view = view;
|
||||
synchronized (this) {
|
||||
if (handlerToLoop == null) {
|
||||
new Thread("Open street bugs layer") {
|
||||
@Override
|
||||
public void run() {
|
||||
Looper.prepare();
|
||||
handlerToLoop = new Handler();
|
||||
Looper.loop();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
}
|
||||
pointOpenedUI = new Paint();
|
||||
pointOpenedUI.setColor(Color.RED);
|
||||
pointOpenedUI.setAlpha(200);
|
||||
pointOpenedUI.setAntiAlias(true);
|
||||
pointClosedUI = new Paint();
|
||||
pointClosedUI.setColor(Color.GREEN);
|
||||
pointClosedUI.setAlpha(200);
|
||||
pointClosedUI.setAntiAlias(true);
|
||||
pixRect.set(0, 0, view.getWidth(), view.getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyLayer() {
|
||||
synchronized (this) {
|
||||
if(handlerToLoop != null){
|
||||
handlerToLoop.post(new Runnable(){
|
||||
@Override
|
||||
public void run() {
|
||||
Looper.myLooper().quit();
|
||||
}
|
||||
});
|
||||
handlerToLoop = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawInScreenPixels() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
if (view.getZoom() >= startZoom) {
|
||||
pixRect.set(0, 0, view.getWidth(), view.getHeight());
|
||||
view.calculateTileRectangle(pixRect, view.getCenterPointX(),
|
||||
view.getCenterPointY(), view.getXTile(), view.getYTile(), tileRect);
|
||||
double topLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), tileRect.top);
|
||||
double leftLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), tileRect.left);
|
||||
double bottomLatitude = MapUtils.getLatitudeFromTile(view.getZoom(), tileRect.bottom);
|
||||
double rightLongitude = MapUtils.getLongitudeFromTile(view.getZoom(), tileRect.right);
|
||||
|
||||
|
||||
// request to load
|
||||
requestToLoad(topLatitude, leftLongitude, bottomLatitude, rightLongitude, view.getZoom());
|
||||
for (OpenStreetBug o : objects) {
|
||||
int x = view.getMapXForPoint(o.getLongitude());
|
||||
int y = view.getMapYForPoint(o.getLatitude());
|
||||
canvas.drawCircle(x, y, getRadiusBug(view.getZoom()), o.isOpened()? pointOpenedUI: pointClosedUI);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public int getRadiusBug(int zoom){
|
||||
if(zoom < startZoom){
|
||||
return 0;
|
||||
} else if(zoom <= 12){
|
||||
return 6;
|
||||
} else if(zoom <= 15){
|
||||
return 10;
|
||||
} else if(zoom == 16){
|
||||
return 13;
|
||||
} else if(zoom == 17){
|
||||
return 15;
|
||||
} else {
|
||||
return 18;
|
||||
}
|
||||
}
|
||||
|
||||
public void requestToLoad(double topLatitude, double leftLongitude, double bottomLatitude,double rightLongitude, final int zoom){
|
||||
boolean inside = cTopLatitude >= topLatitude && cLeftLongitude <= leftLongitude && cRightLongitude >= rightLongitude
|
||||
&& cBottomLatitude <= bottomLatitude;
|
||||
if(!inside || (czoom != zoom && objects.size() >= SEARCH_LIMIT)){
|
||||
handlerToLoop.removeMessages(1);
|
||||
final double nTopLatitude = topLatitude + (topLatitude -bottomLatitude);
|
||||
final double nBottomLatitude = bottomLatitude - (topLatitude -bottomLatitude);
|
||||
final double nLeftLongitude = leftLongitude - (rightLongitude - leftLongitude);
|
||||
final double nRightLongitude = rightLongitude + (rightLongitude - leftLongitude);
|
||||
Message msg = Message.obtain(handlerToLoop, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(handlerToLoop != null && !handlerToLoop.hasMessages(1)){
|
||||
boolean inside = cTopLatitude >= nTopLatitude && cLeftLongitude <= nLeftLongitude && cRightLongitude >= nRightLongitude
|
||||
&& cBottomLatitude <= nBottomLatitude;
|
||||
if (!inside || czoom != zoom) {
|
||||
objects = loadingBugs(nTopLatitude, nLeftLongitude, nBottomLatitude, nRightLongitude);
|
||||
cTopLatitude = nTopLatitude;
|
||||
cLeftLongitude = nLeftLongitude;
|
||||
cRightLongitude = nRightLongitude;
|
||||
cBottomLatitude = nBottomLatitude;
|
||||
czoom = zoom;
|
||||
view.refreshMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
msg.what = 1;
|
||||
handlerToLoop.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected List<OpenStreetBug> loadingBugs(double topLatitude, double leftLongitude, double bottomLatitude,double rightLongitude){
|
||||
List<OpenStreetBug> bugs = new ArrayList<OpenStreetBug>();
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append("http://openstreetbugs.schokokeks.org/api/0.1/getBugs?");
|
||||
b.append("b=").append(bottomLatitude);
|
||||
b.append("&t=").append(topLatitude);
|
||||
b.append("&l=").append(leftLongitude);
|
||||
b.append("&r=").append(rightLongitude);
|
||||
try {
|
||||
URL url = new URL(b.toString());
|
||||
URLConnection connection = url.openConnection();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String st = null;
|
||||
while((st = reader.readLine()) != null){
|
||||
Matcher matcher = patternToParse.matcher(st);
|
||||
if(matcher.find()){
|
||||
OpenStreetBug bug = new OpenStreetBug();
|
||||
bug.setId(Long.parseLong(matcher.group(1)));
|
||||
bug.setLongitude(Double.parseDouble(matcher.group(2)));
|
||||
bug.setLatitude(Double.parseDouble(matcher.group(4)));
|
||||
bug.setName(matcher.group(6));
|
||||
bug.setOpened(matcher.group(7).equals("0"));
|
||||
bugs.add(bug);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("Error loading bugs", e);
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("Error loading bugs", e);
|
||||
} catch (RuntimeException e) {
|
||||
log.warn("Error loading bugs", e);
|
||||
}
|
||||
|
||||
return bugs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongPressEvent(PointF point) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(PointF point) {
|
||||
if (objects != null && !objects.isEmpty()) {
|
||||
int ex = (int) point.x;
|
||||
int ey = (int) point.y;
|
||||
int radius = getRadiusBug(view.getZoom()) * 3 / 2;
|
||||
try {
|
||||
for (OpenStreetBug n : objects) {
|
||||
int x = view.getRotatedMapXForPoint(n.getLatitude(), n.getLongitude());
|
||||
int y = view.getRotatedMapYForPoint(n.getLatitude(), n.getLongitude());
|
||||
if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
|
||||
String format = "Bug : " + n.getName();
|
||||
Toast.makeText(view.getContext(), format, Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// that's really rare case, but is much efficient than introduce synchronized block
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static class OpenStreetBug {
|
||||
private double latitude;
|
||||
private double longitude;
|
||||
private String name;
|
||||
private long id;
|
||||
private boolean opened;
|
||||
public double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
public void setLatitude(double latitude) {
|
||||
this.latitude = latitude;
|
||||
}
|
||||
public double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
public void setLongitude(double longitude) {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public boolean isOpened() {
|
||||
return opened;
|
||||
}
|
||||
public void setOpened(boolean opened) {
|
||||
this.opened = opened;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -16,6 +16,12 @@ public interface OsmandMapLayer {
|
|||
|
||||
public boolean onLongPressEvent(PointF point);
|
||||
|
||||
/**
|
||||
* This method returns whether canvas should be rotated as
|
||||
* map rotated before {@link #onDraw(Canvas)}.
|
||||
* If the layer draws simply layer over screen (not over map)
|
||||
* it should return true.
|
||||
*/
|
||||
public boolean drawInScreenPixels();
|
||||
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ public class PointNavigationLayer implements OsmandMapLayer {
|
|||
private void initUI() {
|
||||
point = new Paint();
|
||||
point.setColor(Color.rgb(250, 80, 80));
|
||||
point.setAlpha(230);
|
||||
point.setAntiAlias(true);
|
||||
point.setStyle(Style.FILL);
|
||||
|
||||
|
|
Loading…
Reference in a new issue