Distance plugin
Before Width: | Height: | Size: 4 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 304 B |
Before Width: | Height: | Size: 304 B |
Before Width: | Height: | Size: 3.9 KiB |
BIN
OsmAnd/res/drawable-hdpi/widget_distance.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
OsmAnd/res/drawable-large/widget_distance.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
OsmAnd/res/drawable-mdpi/widget_distance.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
|
@ -9,6 +9,11 @@
|
|||
1. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
|
||||
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
|
||||
-->
|
||||
<string name="osmand_distance_plugin_description">Measure a distance between two and many points. Add points by a short click and remove by a long press.</string>
|
||||
<string name="osmand_distance_plugin_name">Distance Calculator</string>
|
||||
<string name="use_clear_distance_measurement">Click one more time to clear measurement points.</string>
|
||||
<string name="use_distance_measurement">Tap to make a point, press and hold to delete previous point, click on measurement widget to exit.</string>
|
||||
<string name="map_widget_distancemeasurement">Distance measurement</string>
|
||||
<string name="audionotes_location_not_defined">Location is not defined yet to take with audio notes</string>
|
||||
<string name="monitoring_control_stop">stop</string>
|
||||
<string name="map_widget_audionotes">Audio notes</string>
|
||||
|
@ -1204,6 +1209,4 @@
|
|||
<string name="edit_filter_create_message">Filter {0} has been created</string>
|
||||
<string name="default_buttons_selectall">Select All</string>
|
||||
<string name="email">email</string>
|
||||
<string name="osmand_distance_plugin_description">Measure a distance between two points. Specify the origin / the destination / clear the measurement by a long press.</string>
|
||||
<string name="osmand_distance_plugin_name">Distance Calculator</string>
|
||||
</resources>
|
||||
|
|
|
@ -241,9 +241,6 @@ public class DownloadIndexActivity extends OsmandExpandableListActivity {
|
|||
if(fileItem.isAlreadyDownloaded(listAlreadyDownloaded)){
|
||||
filtered.add(fileItem);
|
||||
}
|
||||
if (listAlreadyDownloaded.containsKey(fileItem.getTargetFileName())) {
|
||||
filtered.add(fileItem);
|
||||
}
|
||||
}
|
||||
listAdapter.setIndexFiles(filtered);
|
||||
} else if (item.getItemId() == DOWNLOAD_FILES_TYPE) {
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
package net.osmand.plus.distancecalculator;
|
||||
|
||||
import net.osmand.osm.LatLon;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.views.OsmandMapLayer;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.location.Location;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* @author Maciej Papiez
|
||||
*
|
||||
*/
|
||||
public class DistanceCalculatorLayer extends OsmandMapLayer {
|
||||
|
||||
private final MapActivity map;
|
||||
private OsmandMapTileView view;
|
||||
private OsmandSettings settings;
|
||||
|
||||
private LatLon originPoint = null;
|
||||
private LatLon destinationPoint = null;
|
||||
private Bitmap originIcon;
|
||||
private Bitmap destinationIcon;
|
||||
private Paint bitmapPaint;
|
||||
|
||||
|
||||
public DistanceCalculatorLayer(MapActivity map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initLayer(OsmandMapTileView view) {
|
||||
this.view = view;
|
||||
this.settings = ((OsmandApplication) map.getApplication()).getSettings();
|
||||
|
||||
originIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pin_origin);
|
||||
destinationIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pin_destination);
|
||||
|
||||
bitmapPaint = new Paint();
|
||||
bitmapPaint.setDither(true);
|
||||
bitmapPaint.setAntiAlias(true);
|
||||
bitmapPaint.setFilterBitmap(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas, RectF latlonRect, RectF tilesRect,
|
||||
DrawSettings settings) {
|
||||
drawIcon(canvas, originPoint, originIcon);
|
||||
drawIcon(canvas, destinationPoint, destinationIcon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a given map pin icon (source or destination point)
|
||||
* @param canvas to draw on
|
||||
* @param point the icon should be drawn at
|
||||
* @param icon to be drawn
|
||||
*/
|
||||
public void drawIcon(Canvas canvas, LatLon point, Bitmap icon) {
|
||||
if (point == null)
|
||||
return;
|
||||
|
||||
double latitude = point.getLatitude();
|
||||
double longitude = point.getLongitude();
|
||||
if (isLocationVisible(latitude, longitude)) {
|
||||
int marginY = icon.getHeight();
|
||||
int locationX = view.getMapXForPoint(longitude);
|
||||
int locationY = view.getMapYForPoint(latitude);
|
||||
canvas.rotate(-view.getRotate(), locationX, locationY);
|
||||
canvas.drawBitmap(icon, locationX, locationY - marginY, bitmapPaint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyLayer() {}
|
||||
|
||||
@Override
|
||||
public boolean drawInScreenPixels() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongPressEvent(PointF point) {
|
||||
if(originPoint == null) {
|
||||
originPoint = view.getLatLonFromScreenPoint(point.x, point.y);
|
||||
} else if(destinationPoint == null) {
|
||||
destinationPoint = view.getLatLonFromScreenPoint(point.x, point.y);
|
||||
|
||||
double startLatitude = originPoint.getLatitude();
|
||||
double startLongitude = originPoint.getLongitude();
|
||||
double endLatitude = destinationPoint.getLatitude();
|
||||
double endLongitude = destinationPoint.getLongitude();
|
||||
float[] results = new float[3];
|
||||
|
||||
Location.distanceBetween(startLatitude, startLongitude, endLatitude, endLongitude, results);
|
||||
|
||||
(Toast.makeText(view.getContext(), "The distance = " + formatDistance(results[0]), Toast.LENGTH_SHORT)).show();
|
||||
|
||||
Log.i("SOMETAG", "Distance calculated: " + results[0]);
|
||||
} else {
|
||||
originPoint = null;
|
||||
destinationPoint = null;
|
||||
}
|
||||
|
||||
view.refreshMap();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a distance into String representation with correct unit
|
||||
* @param distance to be formatted (in meters)
|
||||
* @return the formatted String with the distance and unit (m or km)
|
||||
*/
|
||||
private String formatDistance(float distance) {
|
||||
if(distance < 5000)
|
||||
return String.format("%.2f m", distance);
|
||||
else
|
||||
return String.format("%.2f km", distance / 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param latitude
|
||||
* @param longitude
|
||||
* @return true if the distance measurement point is located on a visible part of map
|
||||
*/
|
||||
private boolean isLocationVisible(double latitude, double longitude) {
|
||||
if(originPoint == null || view == null){
|
||||
return false;
|
||||
}
|
||||
return view.isPointOnTheRotatedMap(latitude, longitude);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,43 @@
|
|||
package net.osmand.plus.distancecalculator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.OsmAndFormatter;
|
||||
import net.osmand.access.AccessibleToast;
|
||||
import net.osmand.osm.LatLon;
|
||||
import net.osmand.osm.MapUtils;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.ApplicationMode;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.views.MapInfoLayer;
|
||||
import net.osmand.plus.views.OsmandMapLayer;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.plus.views.TextInfoControl;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Paint.Cap;
|
||||
import android.graphics.Paint.Join;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* @author Maciej Papiez
|
||||
*
|
||||
*/
|
||||
public class DistanceCalculatorPlugin extends OsmandPlugin {
|
||||
private static final String ID = "osmand.distance";
|
||||
private OsmandApplication app;
|
||||
private DistanceCalculatorLayer distanceCalculatorLayer;
|
||||
private TextInfoControl distanceControl;
|
||||
private List<LatLon> measurementPoints = new ArrayList<LatLon>();
|
||||
|
||||
private int distanceMeasurementMode = 0;
|
||||
|
||||
public DistanceCalculatorPlugin(OsmandApplication app) {
|
||||
this.app = app;
|
||||
|
@ -44,8 +69,160 @@ public class DistanceCalculatorPlugin extends OsmandPlugin {
|
|||
if(distanceCalculatorLayer != null) {
|
||||
activity.getMapView().removeLayer(distanceCalculatorLayer);
|
||||
}
|
||||
distanceCalculatorLayer = new DistanceCalculatorLayer(activity);
|
||||
distanceCalculatorLayer = new DistanceCalculatorLayer();
|
||||
activity.getMapView().addLayer(distanceCalculatorLayer, 8.5f);
|
||||
|
||||
registerWidget(activity);
|
||||
}
|
||||
|
||||
private void registerWidget(MapActivity activity) {
|
||||
MapInfoLayer mapInfoLayer = activity.getMapLayers().getMapInfoLayer();
|
||||
if (mapInfoLayer != null ) {
|
||||
distanceControl = createDistanceControl(activity, mapInfoLayer.getPaintText(), mapInfoLayer.getPaintSubText());
|
||||
mapInfoLayer.getMapInfoControls().registerSideWidget(distanceControl,
|
||||
0/*R.drawable.widget_parking*/, R.string.map_widget_distancemeasurement, "distance.measurement", false,
|
||||
EnumSet.of(ApplicationMode.DEFAULT, ApplicationMode.PEDESTRIAN),
|
||||
EnumSet.noneOf(ApplicationMode.class), 21);
|
||||
mapInfoLayer.recreateControls();
|
||||
updateText();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateText() {
|
||||
if (distanceControl != null) {
|
||||
if (distanceMeasurementMode == 0) {
|
||||
distanceControl.setText(app.getString(R.string.monitoring_control_start), "");
|
||||
} else {
|
||||
float dist = 0;
|
||||
for (int j = 1; j < measurementPoints.size(); j++) {
|
||||
dist += MapUtils.getDistance(measurementPoints.get(j - 1), measurementPoints.get(j));
|
||||
}
|
||||
String ds = OsmAndFormatter.getFormattedDistance(dist, app);
|
||||
int ls = ds.lastIndexOf(' ');
|
||||
if (ls == -1) {
|
||||
distanceControl.setText(ds, null);
|
||||
} else {
|
||||
distanceControl.setText(ds.substring(0, ls), ds.substring(ls + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TextInfoControl createDistanceControl(final MapActivity activity, Paint paintText, Paint paintSubText) {
|
||||
final TextInfoControl distanceControl = new TextInfoControl(activity, 0, paintText, paintSubText);
|
||||
distanceControl.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(distanceMeasurementMode == 0) {
|
||||
AccessibleToast.makeText(app, app.getString(R.string.use_distance_measurement), Toast.LENGTH_LONG).show();
|
||||
distanceMeasurementMode++;
|
||||
} else if(distanceMeasurementMode == 1){
|
||||
AccessibleToast.makeText(app, app.getString(R.string.use_clear_distance_measurement), Toast.LENGTH_LONG).show();
|
||||
distanceMeasurementMode++;
|
||||
} else {
|
||||
measurementPoints.clear();
|
||||
distanceMeasurementMode = 0;
|
||||
}
|
||||
activity.getMapView().refreshMap();
|
||||
updateText();
|
||||
}
|
||||
});
|
||||
distanceControl.setImageDrawable(app.getResources().getDrawable(R.drawable.widget_distance));
|
||||
return distanceControl;
|
||||
}
|
||||
|
||||
|
||||
public class DistanceCalculatorLayer extends OsmandMapLayer {
|
||||
private OsmandMapTileView view;
|
||||
|
||||
private Bitmap originIcon;
|
||||
private Bitmap destinationIcon;
|
||||
private Paint bitmapPaint;
|
||||
|
||||
private Path path;
|
||||
|
||||
private Paint paint;
|
||||
|
||||
public DistanceCalculatorLayer() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initLayer(OsmandMapTileView view) {
|
||||
this.view = view;
|
||||
originIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pin_origin);
|
||||
destinationIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pin_destination);
|
||||
bitmapPaint = new Paint();
|
||||
bitmapPaint.setDither(true);
|
||||
bitmapPaint.setAntiAlias(true);
|
||||
bitmapPaint.setFilterBitmap(true);
|
||||
path = new Path();
|
||||
|
||||
paint = new Paint();
|
||||
paint.setStyle(Style.STROKE);
|
||||
paint.setStrokeWidth(10);
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStrokeCap(Cap.ROUND);
|
||||
paint.setStrokeJoin(Join.ROUND);
|
||||
paint.setColor(0xdd6CB336);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTap(PointF point) {
|
||||
if(distanceMeasurementMode == 1) {
|
||||
LatLon l = view.getLatLonFromScreenPoint(point.x, point.y);
|
||||
measurementPoints.add(l);
|
||||
view.refreshMap();
|
||||
updateText();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongPressEvent(PointF point) {
|
||||
if(distanceMeasurementMode == 1 && measurementPoints.size() > 0) {
|
||||
measurementPoints.remove(measurementPoints.size() - 1);
|
||||
view.refreshMap();
|
||||
updateText();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas, RectF latlonRect, RectF tilesRect, DrawSettings settings) {
|
||||
if (distanceMeasurementMode != 0) {
|
||||
path.reset();
|
||||
for (int i = 0; i < measurementPoints.size(); i++) {
|
||||
LatLon point = measurementPoints.get(i);
|
||||
double lat = point.getLatitude();
|
||||
double lon = point.getLongitude();
|
||||
int locationX = view.getMapXForPoint(lon);
|
||||
int locationY = view.getMapYForPoint(lat);
|
||||
if (view.isPointOnTheRotatedMap(lat, lon)) {
|
||||
int marginY = originIcon.getHeight();
|
||||
canvas.rotate(-view.getRotate(), locationX, locationY);
|
||||
canvas.drawBitmap(distanceMeasurementMode == 1? originIcon : destinationIcon,
|
||||
locationX, locationY - marginY, bitmapPaint);
|
||||
canvas.rotate(view.getRotate(), locationX, locationY);
|
||||
}
|
||||
if (i == 0) {
|
||||
path.moveTo(locationX, locationY);
|
||||
} else {
|
||||
path.lineTo(locationX, locationY);
|
||||
}
|
||||
}
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyLayer() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawInScreenPixels() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,11 +85,13 @@ public class MapStackControl extends ViewGroup {
|
|||
|
||||
public void addStackView(MapInfoControl v) {
|
||||
stackViews.add(v);
|
||||
v.setShadowColor(shadowColor);
|
||||
MapStackControl.this.addView(v, getChildCount());
|
||||
}
|
||||
|
||||
public void addCollapsedView(MapInfoControl v) {
|
||||
collapsedViews.add(v);
|
||||
v.setShadowColor(shadowColor);
|
||||
MapStackControl.this.addView(v, getChildCount());
|
||||
}
|
||||
|
||||
|
@ -195,6 +197,7 @@ public class MapStackControl extends ViewGroup {
|
|||
}
|
||||
|
||||
private final static int MAGIC_CONSTANT_STACK = 3;
|
||||
private int shadowColor;
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
int y = 0;
|
||||
|
@ -245,6 +248,7 @@ public class MapStackControl extends ViewGroup {
|
|||
}
|
||||
|
||||
public void setShadowColor(int shadowColor) {
|
||||
this.shadowColor = shadowColor;
|
||||
for(MapInfoControl c : stackViews) {
|
||||
c.setShadowColor(shadowColor);
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ public class TextInfoControl extends MapInfoControl {
|
|||
|
||||
|
||||
public boolean isVisible() {
|
||||
return text != null && text.length() > 0;
|
||||
return text != null && (text.length() > 0 || subtext != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|