Distance plugin

This commit is contained in:
Victor Shcherb 2012-12-16 01:22:04 +01:00
parent f56436ee0e
commit 9364b9d03b
14 changed files with 192 additions and 154 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -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>

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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;
}
}
}

View file

@ -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);
}

View file

@ -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