Merge pull request #6042 from osmandapp/avoid_roads_fix

Avoid roads fix
This commit is contained in:
Alexey 2018-09-17 12:09:29 +03:00 committed by GitHub
commit ac573d3901
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 180 additions and 195 deletions

View file

@ -13,10 +13,8 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Stack; import java.util.Stack;
@ -56,8 +54,7 @@ public class RoutingConfiguration {
private Map<String, GeneralRouter> routers = new LinkedHashMap<String, GeneralRouter>(); private Map<String, GeneralRouter> routers = new LinkedHashMap<String, GeneralRouter>();
private Map<String, String> attributes = new LinkedHashMap<String, String>(); private Map<String, String> attributes = new LinkedHashMap<String, String>();
private HashMap<Long, Location> impassableRoadLocations = new HashMap<Long, Location>(); private HashMap<Long, Location> impassableRoadLocations = new HashMap<Long, Location>();
private List<RouteDataObject> impassableRoads = new ArrayList<RouteDataObject>();
// Example // Example
// { // {
// impassableRoadLocations.add(23000069L); // impassableRoadLocations.add(23000069L);
@ -104,11 +101,6 @@ public class RoutingConfiguration {
return i; return i;
} }
public List<RouteDataObject> getImpassableRoads() {
return impassableRoads;
}
public Map<Long, Location> getImpassableRoadLocations() { public Map<Long, Location> getImpassableRoadLocations() {
return impassableRoadLocations; return impassableRoadLocations;
} }
@ -116,7 +108,6 @@ public class RoutingConfiguration {
public boolean addImpassableRoad(RouteDataObject route, Location location) { public boolean addImpassableRoad(RouteDataObject route, Location location) {
if (!impassableRoadLocations.containsKey(route.id)){ if (!impassableRoadLocations.containsKey(route.id)){
impassableRoadLocations.put(route.id, location); impassableRoadLocations.put(route.id, location);
impassableRoads.add(route);
return true; return true;
} }
return false; return false;
@ -142,7 +133,6 @@ public class RoutingConfiguration {
public void removeImpassableRoad(RouteDataObject obj) { public void removeImpassableRoad(RouteDataObject obj) {
impassableRoadLocations.remove(obj.id); impassableRoadLocations.remove(obj.id);
impassableRoads.remove(obj);
} }
} }

View file

@ -49,13 +49,15 @@ public class CurrentPositionHelper {
this.app = app; this.app = app;
} }
public boolean getRouteSegment(Location loc, @Nullable ApplicationMode appMode, public boolean getRouteSegment(Location loc,
@Nullable ApplicationMode appMode,
boolean cancelPreviousSearch,
ResultMatcher<RouteDataObject> result) { ResultMatcher<RouteDataObject> result) {
return scheduleRouteSegmentFind(loc, false, true, null, result, appMode); return scheduleRouteSegmentFind(loc, false, true, cancelPreviousSearch, null, result, appMode);
} }
public boolean getGeocodingResult(Location loc, ResultMatcher<GeocodingResult> result) { public boolean getGeocodingResult(Location loc, ResultMatcher<GeocodingResult> result) {
return scheduleRouteSegmentFind(loc, false, false, result, null, null); return scheduleRouteSegmentFind(loc, false, false, true, result, null, null);
} }
public RouteDataObject getLastKnownRouteSegment(Location loc) { public RouteDataObject getLastKnownRouteSegment(Location loc) {
@ -68,12 +70,12 @@ public class CurrentPositionHelper {
return r; return r;
} }
if (r == null) { if (r == null) {
scheduleRouteSegmentFind(loc, true, false, null, null, null); scheduleRouteSegmentFind(loc, true, false, true, null, null, null);
return null; return null;
} }
double d = getOrthogonalDistance(r, loc); double d = getOrthogonalDistance(r, loc);
if (d > 15) { if (d > 15) {
scheduleRouteSegmentFind(loc, true, false, null, null, null); scheduleRouteSegmentFind(loc, true, false, true, null, null, null);
} }
if (d < 70) { if (d < 70) {
return r; return r;
@ -90,6 +92,7 @@ public class CurrentPositionHelper {
private boolean scheduleRouteSegmentFind(final Location loc, private boolean scheduleRouteSegmentFind(final Location loc,
final boolean storeFound, final boolean storeFound,
final boolean allowEmptyNames, final boolean allowEmptyNames,
final boolean cancelPreviousSearch,
@Nullable final ResultMatcher<GeocodingResult> geoCoding, @Nullable final ResultMatcher<GeocodingResult> geoCoding,
@Nullable final ResultMatcher<RouteDataObject> result, @Nullable final ResultMatcher<RouteDataObject> result,
@Nullable final ApplicationMode appMode) { @Nullable final ApplicationMode appMode) {
@ -106,7 +109,7 @@ public class CurrentPositionHelper {
singleThreadExecutor.submit(new Runnable() { singleThreadExecutor.submit(new Runnable() {
@Override @Override
public void run() { public void run() {
processGeocoding(loc, geoCoding, storeFound, allowEmptyNames, result, appMode, request, finalRequestNumber); processGeocoding(loc, geoCoding, storeFound, allowEmptyNames, result, appMode, request, finalRequestNumber, cancelPreviousSearch);
} }
}); });
res = true; res = true;
@ -155,9 +158,10 @@ public class CurrentPositionHelper {
@Nullable final ResultMatcher<RouteDataObject> result, @Nullable final ResultMatcher<RouteDataObject> result,
@Nullable ApplicationMode appMode, @Nullable ApplicationMode appMode,
int request, int request,
@NonNull AtomicInteger requestNumber) { @NonNull AtomicInteger requestNumber,
boolean cancelPreviousSearch) {
if (request != requestNumber.get()) { if (cancelPreviousSearch && request != requestNumber.get()) {
return; return;
} }

View file

@ -854,10 +854,12 @@ public class OsmAndLocationProvider implements SensorEventListener {
public RouteDataObject getLastKnownRouteSegment() { public RouteDataObject getLastKnownRouteSegment() {
return currentPositionHelper.getLastKnownRouteSegment(getLastKnownLocation()); return currentPositionHelper.getLastKnownRouteSegment(getLastKnownLocation());
} }
public boolean getRouteSegment(net.osmand.Location loc, @Nullable ApplicationMode appMode, public boolean getRouteSegment(net.osmand.Location loc,
@Nullable ApplicationMode appMode,
boolean cancelPreviousSearch,
ResultMatcher<RouteDataObject> result) { ResultMatcher<RouteDataObject> result) {
return currentPositionHelper.getRouteSegment(loc, appMode, result); return currentPositionHelper.getRouteSegment(loc, appMode, cancelPreviousSearch, result);
} }
public boolean getGeocodingResult(net.osmand.Location loc, ResultMatcher<GeocodingResult> result) { public boolean getGeocodingResult(net.osmand.Location loc, ResultMatcher<GeocodingResult> result) {

View file

@ -1,9 +1,12 @@
package net.osmand.plus.helpers; package net.osmand.plus.helpers;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
@ -18,6 +21,7 @@ import net.osmand.ResultMatcher;
import net.osmand.binary.RouteDataObject; import net.osmand.binary.RouteDataObject;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.PointDescription; import net.osmand.data.PointDescription;
import net.osmand.plus.AppInitializer;
import net.osmand.plus.ApplicationMode; import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
@ -25,43 +29,61 @@ import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MapContextMenu; import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.views.AnimateDraggingMapThread;
import net.osmand.plus.views.ContextMenuLayer; import net.osmand.plus.views.ContextMenuLayer;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.LinkedHashMap;
import java.util.Map;
public class AvoidSpecificRoads { public class AvoidSpecificRoads {
private List<RouteDataObject> impassableRoads;
private OsmandApplication app; private OsmandApplication app;
public AvoidSpecificRoads(OsmandApplication app) { private Map<LatLon, RouteDataObject> impassableRoads = new LinkedHashMap<>();
public AvoidSpecificRoads(final OsmandApplication app) {
this.app = app; this.app = app;
} for (LatLon latLon : app.getSettings().getImpassableRoadPoints()) {
impassableRoads.put(latLon, null);
}
if (app.isApplicationInitializing()) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
app.getAppInitializer().addListener(new AppInitializer.AppInitializeListener() {
@Override
public void onProgress(AppInitializer init, AppInitializer.InitEvents event) {
public void initPreservedData() { }
List<LatLon> impassibleRoads = app.getSettings().getImpassableRoadPoints();
for (LatLon impassibleRoad : impassibleRoads) { @Override
addImpassableRoad(null, impassibleRoad, false, null, true); public void onFinish(AppInitializer init) {
initRouteObjects();
init.removeListener(this);
}
});
}
});
} else {
initRouteObjects();
} }
} }
private List<RouteDataObject> getImpassableRoads() { public Map<LatLon, RouteDataObject> getImpassableRoads() {
if (impassableRoads == null) {
impassableRoads = app.getDefaultRoutingConfig().getImpassableRoads();
}
return impassableRoads; return impassableRoads;
} }
private ArrayAdapter<RouteDataObject> createAdapter(final MapActivity ctx) { private void initRouteObjects() {
final ArrayList<RouteDataObject> points = new ArrayList<>(); for (LatLon latLon : impassableRoads.keySet()) {
points.addAll(getImpassableRoads()); addImpassableRoad(null, latLon, false, true);
final LatLon mapLocation = ctx.getMapLocation(); }
return new ArrayAdapter<RouteDataObject>(ctx, }
R.layout.waypoint_reached, R.id.title, points) {
private ArrayAdapter<LatLon> createAdapter(final MapActivity ctx) {
final ArrayList<LatLon> points = new ArrayList<>(impassableRoads.keySet());
final LatLon mapLocation = ctx.getMapLocation();
return new ArrayAdapter<LatLon>(ctx, R.layout.waypoint_reached, R.id.title, points) {
@NonNull @NonNull
@Override @Override
public View getView(final int position, View convertView, @NonNull ViewGroup parent) { public View getView(final int position, View convertView, @NonNull ViewGroup parent) {
@ -69,30 +91,22 @@ public class AvoidSpecificRoads {
if (v == null || v.findViewById(R.id.info_close) == null) { if (v == null || v.findViewById(R.id.info_close) == null) {
v = ctx.getLayoutInflater().inflate(R.layout.waypoint_reached, parent, false); v = ctx.getLayoutInflater().inflate(R.layout.waypoint_reached, parent, false);
} }
final RouteDataObject obj = getItem(position); final LatLon item = getItem(position);
v.findViewById(R.id.all_points).setVisibility(View.GONE); v.findViewById(R.id.all_points).setVisibility(View.GONE);
((ImageView) v.findViewById(R.id.waypoint_icon)).setImageDrawable( ((ImageView) v.findViewById(R.id.waypoint_icon))
app.getUIUtilities().getThemedIcon(R.drawable.ic_action_road_works_dark)); .setImageDrawable(getIcon(R.drawable.ic_action_road_works_dark));
double dist = MapUtils.getDistance(mapLocation, MapUtils.get31LatitudeY(obj.getPoint31YTile(0)), ((TextView) v.findViewById(R.id.waypoint_dist)).setText(getDist(mapLocation, item));
MapUtils.get31LongitudeX(obj.getPoint31XTile(0))); ((TextView) v.findViewById(R.id.waypoint_text)).setText(getText(item));
((TextView) v.findViewById(R.id.waypoint_dist)).setText(OsmAndFormatter.getFormattedDistance((float) dist, app));
((TextView) v.findViewById(R.id.waypoint_text)).setText(getText(obj));
ImageButton remove = (ImageButton) v.findViewById(R.id.info_close); ImageButton remove = (ImageButton) v.findViewById(R.id.info_close);
remove.setVisibility(View.VISIBLE); remove.setVisibility(View.VISIBLE);
remove.setImageDrawable(app.getUIUtilities().getThemedIcon( remove.setImageDrawable(getIcon(R.drawable.ic_action_remove_dark));
R.drawable.ic_action_remove_dark));
remove.setOnClickListener(new View.OnClickListener() { remove.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
remove(obj); remove(item);
removeImpassableRoad(obj); removeImpassableRoad(item);
notifyDataSetChanged(); notifyDataSetChanged();
RoutingHelper rh = app.getRoutingHelper(); recalculateRoute();
if (rh.isRouteCalculated() || rh.isRouteBeingCalculated()) {
rh.recalculateRouteDueToSettingsChange();
}
} }
}); });
return v; return v;
@ -100,41 +114,73 @@ public class AvoidSpecificRoads {
}; };
} }
public void removeImpassableRoad(RouteDataObject obj) { private Drawable getIcon(@DrawableRes int iconId) {
app.getSettings().removeImpassableRoad(getLocation(obj)); return app.getUIUtilities().getThemedIcon(iconId);
app.getDefaultRoutingConfig().removeImpassableRoad(obj);
} }
private String getDist(@NonNull LatLon loc, @Nullable LatLon point) {
double dist = point == null ? 0 : MapUtils.getDistance(loc, point);
return OsmAndFormatter.getFormattedDistance((float) dist, app);
}
protected String getText(RouteDataObject obj) { private String getText(@Nullable LatLon point) {
String name = RoutingHelper.formatStreetName(obj.getName(app.getSettings().MAP_PREFERRED_LOCALE.get(), if (point != null) {
app.getSettings().MAP_TRANSLITERATE_NAMES.get()), RouteDataObject obj = impassableRoads.get(point);
obj.getRef(app.getSettings().MAP_PREFERRED_LOCALE.get(), app.getSettings().MAP_TRANSLITERATE_NAMES.get(), true), if (obj != null) {
obj.getDestinationName(app.getSettings().MAP_PREFERRED_LOCALE.get(), app.getSettings().MAP_TRANSLITERATE_NAMES.get(), true), String locale = app.getSettings().MAP_PREFERRED_LOCALE.get();
app.getString(R.string.towards)); boolean transliterate = app.getSettings().MAP_TRANSLITERATE_NAMES.get();
String name = RoutingHelper.formatStreetName(
obj.getName(locale, transliterate),
obj.getRef(locale, transliterate, true),
obj.getDestinationName(locale, transliterate, true),
app.getString(R.string.towards)
);
if (!TextUtils.isEmpty(name)) {
return name;
}
}
}
return app.getString(R.string.shared_string_road);
}
return Algorithms.isEmpty(name) ? app.getString(R.string.shared_string_road) : name; private void recalculateRoute() {
RoutingHelper rh = app.getRoutingHelper();
if (rh.isRouteCalculated() || rh.isRouteBeingCalculated()) {
rh.recalculateRouteDueToSettingsChange();
}
}
private void removeImpassableRoad(LatLon latLon) {
app.getSettings().removeImpassableRoad(latLon);
RouteDataObject obj = impassableRoads.remove(latLon);
if (obj != null) {
app.getDefaultRoutingConfig().removeImpassableRoad(obj);
}
}
public void removeImpassableRoad(RouteDataObject obj) {
removeImpassableRoad(getLocation(obj));
} }
public void showDialog(@NonNull final MapActivity mapActivity) { public void showDialog(@NonNull final MapActivity mapActivity) {
AlertDialog.Builder bld = new AlertDialog.Builder(mapActivity); AlertDialog.Builder bld = new AlertDialog.Builder(mapActivity);
bld.setTitle(R.string.impassable_road); bld.setTitle(R.string.impassable_road);
if (getImpassableRoads().size() == 0) { if (impassableRoads.isEmpty()) {
bld.setMessage(R.string.avoid_roads_msg); bld.setMessage(R.string.avoid_roads_msg);
} else { } else {
final ArrayAdapter<?> listAdapter = createAdapter(mapActivity); final ArrayAdapter<LatLon> listAdapter = createAdapter(mapActivity);
bld.setAdapter(listAdapter, new DialogInterface.OnClickListener() { bld.setAdapter(listAdapter, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
RouteDataObject obj = getImpassableRoads().get(which); LatLon point = listAdapter.getItem(which);
double lat = MapUtils.get31LatitudeY(obj.getPoint31YTile(0)); if (point != null) {
double lon = MapUtils.get31LongitudeX(obj.getPoint31XTile(0)); showOnMap(mapActivity, point.getLatitude(), point.getLongitude(), getText(point));
showOnMap(mapActivity, lat, lon, getText(obj), dialog); }
dialog.dismiss();
} }
}); });
} }
bld.setPositiveButton(R.string.shared_string_select_on_map, new DialogInterface.OnClickListener() { bld.setPositiveButton(R.string.shared_string_select_on_map, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialogInterface, int i) { public void onClick(DialogInterface dialogInterface, int i) {
@ -145,31 +191,27 @@ public class AvoidSpecificRoads {
bld.show(); bld.show();
} }
private void selectFromMap(final MapActivity mapActivity) { private void selectFromMap(final MapActivity mapActivity) {
ContextMenuLayer cm = mapActivity.getMapLayers().getContextMenuLayer(); ContextMenuLayer cm = mapActivity.getMapLayers().getContextMenuLayer();
cm.setSelectOnMap(new CallbackWithObject<LatLon>() { cm.setSelectOnMap(new CallbackWithObject<LatLon>() {
@Override @Override
public boolean processResult(LatLon result) { public boolean processResult(LatLon result) {
addImpassableRoad(mapActivity, result, true, null, false); addImpassableRoad(mapActivity, result, true, false);
return true; return true;
} }
}); });
} }
public void addImpassableRoad(@Nullable final MapActivity activity, public void addImpassableRoad(@Nullable final MapActivity activity,
@NonNull final LatLon loc, @NonNull final LatLon loc,
final boolean showDialog, final boolean showDialog,
@Nullable final AvoidSpecificRoadsCallback callback,
final boolean skipWritingSettings) { final boolean skipWritingSettings) {
final Location ll = new Location(""); final Location ll = new Location("");
ll.setLatitude(loc.getLatitude()); ll.setLatitude(loc.getLatitude());
ll.setLongitude(loc.getLongitude()); ll.setLongitude(loc.getLongitude());
ApplicationMode appMode = app.getRoutingHelper().getAppMode(); ApplicationMode appMode = app.getRoutingHelper().getAppMode();
app.getLocationProvider().getRouteSegment(ll, appMode, new ResultMatcher<RouteDataObject>() { app.getLocationProvider().getRouteSegment(ll, appMode, false, new ResultMatcher<RouteDataObject>() {
@Override @Override
public boolean publish(RouteDataObject object) { public boolean publish(RouteDataObject object) {
@ -177,22 +219,15 @@ public class AvoidSpecificRoads {
if (activity != null) { if (activity != null) {
Toast.makeText(activity, R.string.error_avoid_specific_road, Toast.LENGTH_LONG).show(); Toast.makeText(activity, R.string.error_avoid_specific_road, Toast.LENGTH_LONG).show();
} }
if (callback != null) {
callback.onAddImpassableRoad(false, null);
}
} else { } else {
addImpassableRoadInternal(object, ll, showDialog, activity, loc); addImpassableRoadInternal(object, ll, showDialog, activity, loc);
if (callback != null) {
callback.onAddImpassableRoad(true, object);
}
} }
return true; return true;
} }
@Override @Override
public boolean isCancelled() { public boolean isCancelled() {
return callback != null && callback.isCancelled(); return false;
} }
}); });
@ -201,19 +236,17 @@ public class AvoidSpecificRoads {
} }
} }
public void replaceImpassableRoad(final MapActivity activity, final RouteDataObject currentObject, public void replaceImpassableRoad(final MapActivity activity,
final LatLon loc, final boolean showDialog, final RouteDataObject currentObject,
final LatLon newLoc,
final boolean showDialog,
final AvoidSpecificRoadsCallback callback) { final AvoidSpecificRoadsCallback callback) {
LatLon latLon = getLocation(currentObject);
app.getSettings().moveImpassableRoad(latLon, loc);
final Location ll = new Location(""); final Location ll = new Location("");
ll.setLatitude(loc.getLatitude()); ll.setLatitude(newLoc.getLatitude());
ll.setLongitude(loc.getLongitude()); ll.setLongitude(newLoc.getLongitude());
ApplicationMode appMode = app.getRoutingHelper().getAppMode(); ApplicationMode appMode = app.getRoutingHelper().getAppMode();
app.getLocationProvider().getRouteSegment(ll, appMode, new ResultMatcher<RouteDataObject>() { app.getLocationProvider().getRouteSegment(ll, appMode, false, new ResultMatcher<RouteDataObject>() {
@Override @Override
public boolean publish(RouteDataObject object) { public boolean publish(RouteDataObject object) {
@ -223,8 +256,11 @@ public class AvoidSpecificRoads {
callback.onAddImpassableRoad(false, null); callback.onAddImpassableRoad(false, null);
} }
} else { } else {
final LatLon oldLoc = getLocation(currentObject);
app.getSettings().moveImpassableRoad(oldLoc, newLoc);
impassableRoads.remove(oldLoc);
app.getDefaultRoutingConfig().removeImpassableRoad(currentObject); app.getDefaultRoutingConfig().removeImpassableRoad(currentObject);
addImpassableRoadInternal(object, ll, showDialog, activity, loc); addImpassableRoadInternal(object, ll, showDialog, activity, newLoc);
if (callback != null) { if (callback != null) {
callback.onAddImpassableRoad(true, object); callback.onAddImpassableRoad(true, object);
@ -245,16 +281,15 @@ public class AvoidSpecificRoads {
boolean showDialog, boolean showDialog,
@Nullable MapActivity activity, @Nullable MapActivity activity,
@NonNull LatLon loc) { @NonNull LatLon loc) {
if (!app.getDefaultRoutingConfig().addImpassableRoad(object, ll)) { if (app.getDefaultRoutingConfig().addImpassableRoad(object, ll)) {
impassableRoads.put(loc, object);
} else {
LatLon location = getLocation(object); LatLon location = getLocation(object);
if (location != null) { if (location != null) {
app.getSettings().removeImpassableRoad(getLocation(object)); app.getSettings().removeImpassableRoad(location);
} }
} }
RoutingHelper rh = app.getRoutingHelper(); recalculateRoute();
if (rh.isRouteCalculated() || rh.isRouteBeingCalculated()) {
rh.recalculateRouteDueToSettingsChange();
}
if (activity != null) { if (activity != null) {
if (showDialog) { if (showDialog) {
showDialog(activity); showDialog(activity);
@ -267,21 +302,14 @@ public class AvoidSpecificRoads {
} }
} }
private void showOnMap(MapActivity ctx, double lat, double lon, String name, private void showOnMap(MapActivity ctx, double lat, double lon, String name) {
DialogInterface dialog) { int zoom = ctx.getMapView().getZoom() < 15 ? 15 : ctx.getMapView().getZoom();
AnimateDraggingMapThread thread = ctx.getMapView().getAnimatedDraggingThread(); PointDescription pd = new PointDescription("", name);
int fZoom = ctx.getMapView().getZoom() < 15 ? 15 : ctx.getMapView().getZoom(); ctx.getMyApplication().getSettings().setMapLocationToShow(lat, lon, zoom, pd, false, null);
if (thread.isAnimating()) { MapActivity.launchMapActivityMoveToTop(ctx);
ctx.getMapView().setIntZoom(fZoom);
ctx.getMapView().setLatLon(lat, lon);
} else {
thread.startMoving(lat, lon, fZoom, true);
}
ctx.getContextMenu().show(new LatLon(lat, lon), new PointDescription("", name), null);
dialog.dismiss();
} }
private LatLon getLocation(RouteDataObject object) { public LatLon getLocation(RouteDataObject object) {
Location location = app.getDefaultRoutingConfig().getImpassableRoadLocations().get(object.getId()); Location location = app.getDefaultRoutingConfig().getImpassableRoadLocations().get(object.getId());
return location == null ? null : new LatLon(location.getLatitude(), location.getLongitude()); return location == null ? null : new LatLon(location.getLatitude(), location.getLongitude());
} }

View file

@ -33,7 +33,7 @@ public class PointDescriptionMenuController extends MenuController {
MapActivity activity = getMapActivity(); MapActivity activity = getMapActivity();
if (activity != null) { if (activity != null) {
AvoidSpecificRoads roads = activity.getMyApplication().getAvoidSpecificRoads(); AvoidSpecificRoads roads = activity.getMyApplication().getAvoidSpecificRoads();
roads.addImpassableRoad(activity, getLatLon(), false, null, false); roads.addImpassableRoad(activity, getLatLon(), false, false);
} }
} }
}; };

View file

@ -3,12 +3,13 @@ package net.osmand.plus.views;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.PointF; import android.graphics.PointF;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import net.osmand.Location;
import net.osmand.binary.RouteDataObject; import net.osmand.binary.RouteDataObject;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.PointDescription; import net.osmand.data.PointDescription;
@ -16,27 +17,25 @@ import net.osmand.data.RotatedTileBox;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AvoidSpecificRoads;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidSpecificRoadsCallback; import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidSpecificRoadsCallback;
import net.osmand.plus.views.ContextMenuLayer.ApplyMovedObjectCallback; import net.osmand.plus.views.ContextMenuLayer.ApplyMovedObjectCallback;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
public class ImpassableRoadsLayer extends OsmandMapLayer implements public class ImpassableRoadsLayer extends OsmandMapLayer implements
ContextMenuLayer.IContextMenuProvider, ContextMenuLayer.IMoveObjectProvider { ContextMenuLayer.IContextMenuProvider, ContextMenuLayer.IMoveObjectProvider {
private static final int startZoom = 10; private static final int START_ZOOM = 10;
private final MapActivity activity;
private Bitmap roadWorkIcon;
private Paint paint;
private Map<Long, Location> impassableRoadLocations;
private List<RouteDataObject> impassableRoads;
private final MapActivity activity;
private AvoidSpecificRoads avoidSpecificRoads;
private ContextMenuLayer contextMenuLayer; private ContextMenuLayer contextMenuLayer;
private Set<StoredRoadDataObject> storedRoadDataObjects; private Bitmap roadWorkIcon;
private Paint activePaint;
private Paint paint;
public ImpassableRoadsLayer(MapActivity activity) { public ImpassableRoadsLayer(MapActivity activity) {
this.activity = activity; this.activity = activity;
@ -44,76 +43,55 @@ public class ImpassableRoadsLayer extends OsmandMapLayer implements
@Override @Override
public void initLayer(OsmandMapTileView view) { public void initLayer(OsmandMapTileView view) {
roadWorkIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pin_avoid_road); avoidSpecificRoads = activity.getMyApplication().getAvoidSpecificRoads();
paint = new Paint();
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class); contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
roadWorkIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pin_avoid_road);
List<LatLon> impassibleRoads = activity.getMyApplication().getSettings().getImpassableRoadPoints(); activePaint = new Paint();
storedRoadDataObjects = new HashSet<>(impassibleRoads.size()); ColorMatrix matrix = new ColorMatrix();
for (LatLon impassibleRoad : impassibleRoads) { matrix.setSaturation(0);
storedRoadDataObjects.add(new StoredRoadDataObject(impassibleRoad)); paint = new Paint();
} paint.setColorFilter(new ColorMatrixColorFilter(matrix));
} }
@Override @Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (contextMenuLayer.getMoveableObject() instanceof RouteDataObject) { if (contextMenuLayer.getMoveableObject() instanceof RouteDataObject) {
PointF pf = contextMenuLayer.getMovableCenterPoint(tileBox); PointF pf = contextMenuLayer.getMovableCenterPoint(tileBox);
drawPoint(canvas, pf.x, pf.y); drawPoint(canvas, pf.x, pf.y, true);
} }
} }
@Override @Override
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (tileBox.getZoom() >= startZoom) { if (tileBox.getZoom() >= START_ZOOM) {
for (long id : getImpassableRoadLocations().keySet()) { for (Map.Entry<LatLon, RouteDataObject> entry : avoidSpecificRoads.getImpassableRoads().entrySet()) {
if (contextMenuLayer.getMoveableObject() instanceof RouteDataObject) { LatLon location = entry.getKey();
RouteDataObject road = entry.getValue();
if (road != null && contextMenuLayer.getMoveableObject() instanceof RouteDataObject) {
RouteDataObject object = (RouteDataObject) contextMenuLayer.getMoveableObject(); RouteDataObject object = (RouteDataObject) contextMenuLayer.getMoveableObject();
if (object.id == id) { if (object.id == road.id) {
continue; continue;
} }
} }
Location location = getImpassableRoadLocations().get(id);
final double latitude = location.getLatitude(); final double latitude = location.getLatitude();
final double longitude = location.getLongitude(); final double longitude = location.getLongitude();
if (tileBox.containsLatLon(latitude, longitude)) { if (tileBox.containsLatLon(latitude, longitude)) {
drawPoint(canvas, tileBox, latitude, longitude); drawPoint(canvas, tileBox, latitude, longitude, road != null);
}
}
for (StoredRoadDataObject storedRoadDataObject : storedRoadDataObjects) {
final LatLon latLon = storedRoadDataObject.getLatLon();
if (tileBox.containsLatLon(latLon)) {
drawPoint(canvas, tileBox, latLon.getLatitude(), latLon.getLongitude());
} }
} }
} }
} }
private void drawPoint(Canvas canvas, RotatedTileBox tileBox, double latitude, double longitude) { private void drawPoint(Canvas canvas, RotatedTileBox tileBox, double latitude, double longitude, boolean active) {
float x = tileBox.getPixXFromLatLon(latitude, longitude); float x = tileBox.getPixXFromLatLon(latitude, longitude);
float y = tileBox.getPixYFromLatLon(latitude, longitude); float y = tileBox.getPixYFromLatLon(latitude, longitude);
drawPoint(canvas, x, y); drawPoint(canvas, x, y, active);
} }
private void drawPoint(Canvas canvas, float x, float y) { private void drawPoint(Canvas canvas, float x, float y, boolean active) {
float left = x - roadWorkIcon.getWidth() / 2; float left = x - roadWorkIcon.getWidth() / 2;
float top = y - roadWorkIcon.getHeight(); float top = y - roadWorkIcon.getHeight();
canvas.drawBitmap(roadWorkIcon, left, top, paint); canvas.drawBitmap(roadWorkIcon, left, top, active ? activePaint : paint);
}
private Map<Long, Location> getImpassableRoadLocations() {
if (impassableRoadLocations == null) {
impassableRoadLocations = activity.getMyApplication().getDefaultRoutingConfig().getImpassableRoadLocations();
}
return impassableRoadLocations;
}
private List<RouteDataObject> getImpassableRoads() {
if (impassableRoads == null) {
impassableRoads = activity.getMyApplication().getDefaultRoutingConfig().getImpassableRoads();
}
return impassableRoads;
} }
@Override @Override
@ -128,7 +106,7 @@ public class ImpassableRoadsLayer extends OsmandMapLayer implements
private int getRadiusPoi(RotatedTileBox tb) { private int getRadiusPoi(RotatedTileBox tb) {
int r; int r;
if (tb.getZoom() < startZoom) { if (tb.getZoom() < START_ZOOM) {
r = 0; r = 0;
} else { } else {
r = 15; r = 15;
@ -162,15 +140,16 @@ public class ImpassableRoadsLayer extends OsmandMapLayer implements
@Override @Override
public void collectObjectsFromPoint(PointF point, RotatedTileBox tileBox, List<Object> o, boolean unknownLocation) { public void collectObjectsFromPoint(PointF point, RotatedTileBox tileBox, List<Object> o, boolean unknownLocation) {
if (tileBox.getZoom() >= startZoom) { if (tileBox.getZoom() >= START_ZOOM) {
int ex = (int) point.x; int ex = (int) point.x;
int ey = (int) point.y; int ey = (int) point.y;
int compare = getRadiusPoi(tileBox); int compare = getRadiusPoi(tileBox);
int radius = compare * 3 / 2; int radius = compare * 3 / 2;
for (RouteDataObject road : getImpassableRoads()) { for (Map.Entry<LatLon, RouteDataObject> entry : avoidSpecificRoads.getImpassableRoads().entrySet()) {
Location location = getImpassableRoadLocations().get(road.getId()); LatLon location = entry.getKey();
if (location != null) { RouteDataObject road = entry.getValue();
if (location != null && road != null) {
int x = (int) tileBox.getPixXFromLatLon(location.getLatitude(), location.getLongitude()); int x = (int) tileBox.getPixXFromLatLon(location.getLatitude(), location.getLongitude());
int y = (int) tileBox.getPixYFromLatLon(location.getLatitude(), location.getLongitude()); int y = (int) tileBox.getPixYFromLatLon(location.getLatitude(), location.getLongitude());
if (calculateBelongs(ex, ey, x, y, compare)) { if (calculateBelongs(ex, ey, x, y, compare)) {
@ -180,18 +159,12 @@ public class ImpassableRoadsLayer extends OsmandMapLayer implements
} }
} }
} }
if (!storedRoadDataObjects.isEmpty()) {
activity.getMyApplication().getAvoidSpecificRoads().initPreservedData();
storedRoadDataObjects.clear();
}
} }
@Override @Override
public LatLon getObjectLocation(Object o) { public LatLon getObjectLocation(Object o) {
if (o instanceof RouteDataObject) { if (o instanceof RouteDataObject) {
RouteDataObject route = (RouteDataObject) o; return avoidSpecificRoads.getLocation((RouteDataObject) o);
Location location = impassableRoadLocations.get(route.getId());
return new LatLon(location.getLatitude(), location.getLongitude());
} }
return null; return null;
} }
@ -232,16 +205,4 @@ public class ImpassableRoadsLayer extends OsmandMapLayer implements
}); });
} }
} }
private static class StoredRoadDataObject {
private final LatLon latLon;
private StoredRoadDataObject(LatLon latLon) {
this.latLon = latLon;
}
public LatLon getLatLon() {
return latLon;
}
}
} }