Avoid roads second part

This commit is contained in:
Vitaliy 2020-02-18 16:40:39 +02:00
parent bd0d4a9c9e
commit 1cb49fe402
4 changed files with 180 additions and 32 deletions

View file

@ -116,9 +116,9 @@ public class RoutingConfiguration {
return impassableRoadLocations; return impassableRoadLocations;
} }
public boolean addImpassableRoad(RouteDataObject route) { public boolean addImpassableRoad(long routeId) {
if (!impassableRoadLocations.contains(route.id)) { if (!impassableRoadLocations.contains(routeId)) {
impassableRoadLocations.add(route.id); impassableRoadLocations.add(routeId);
return true; return true;
} }
return false; return false;

View file

@ -629,6 +629,7 @@ public class AppInitializer implements IProgress {
if (!customConfigs.isEmpty()) { if (!customConfigs.isEmpty()) {
app.getCustomRoutingConfigs().putAll(customConfigs); app.getCustomRoutingConfigs().putAll(customConfigs);
} }
app.avoidSpecificRoads.initRouteObjects(false);
callback.onRoutingFilesLoaded(); callback.onRoutingFilesLoaded();
} }
@ -739,7 +740,6 @@ public class AppInitializer implements IProgress {
notifyEvent(InitEvents.RESTORE_BACKUPS); notifyEvent(InitEvents.RESTORE_BACKUPS);
app.mapMarkersHelper.syncAllGroupsAsync(); app.mapMarkersHelper.syncAllGroupsAsync();
app.searchUICore.initSearchUICore(); app.searchUICore.initSearchUICore();
app.avoidSpecificRoads.initRouteObjects(false);
checkLiveUpdatesAlerts(); checkLiveUpdatesAlerts();

View file

@ -2798,9 +2798,136 @@ public class OsmandSettings {
} }
private class ImpassableRoadsStorage extends MapPointsStorage { private class ImpassableRoadsStorage extends MapPointsStorage {
protected String roadsIdsKey;
public ImpassableRoadsStorage() { public ImpassableRoadsStorage() {
pointsKey = IMPASSABLE_ROAD_POINTS; pointsKey = IMPASSABLE_ROAD_POINTS;
descriptionsKey = IMPASSABLE_ROADS_DESCRIPTIONS; descriptionsKey = IMPASSABLE_ROADS_DESCRIPTIONS;
roadsIdsKey = IMPASSABLE_ROADS_IDS;
}
public List<AvoidRoadInfo> getImpassableRoadsInfo() {
List<LatLon> points = mImpassableRoadsStorage.getPoints();
List<String> descriptions = mImpassableRoadsStorage.getPointDescriptions(points.size());
List<Long> roadIds = getRoadIds(points.size());
List<AvoidRoadInfo> avoidRoadsInfo = new ArrayList<>();
for (int i = 0; i < points.size(); i++) {
LatLon latLon = points.get(i);
PointDescription description = PointDescription.deserializeFromString(descriptions.get(i), null);
AvoidRoadInfo avoidRoadInfo = new AvoidRoadInfo();
avoidRoadInfo.id = roadIds.get(i);
avoidRoadInfo.lat = latLon.getLatitude();
avoidRoadInfo.lon = latLon.getLongitude();
avoidRoadInfo.name = description.getName();
avoidRoadsInfo.add(avoidRoadInfo);
}
return avoidRoadsInfo;
}
public boolean addImpassableRoadInfo(AvoidRoadInfo avoidRoadInfo) {
List<LatLon> points = getPoints();
List<String> descriptions = getPointDescriptions(points.size());
List<Long> roadIds = getRoadIds(points.size());
points.add(0, new LatLon(avoidRoadInfo.lat, avoidRoadInfo.lon));
descriptions.add(0, PointDescription.serializeToString(new PointDescription("", avoidRoadInfo.name)));
roadIds.add(0, avoidRoadInfo.id);
return savePoints(points, descriptions) && saveRoadIds(roadIds);
}
public boolean updateImpassableRoadInfo(AvoidRoadInfo avoidRoadInfo) {
List<LatLon> points = getPoints();
List<Long> roadIds = getRoadIds(points.size());
List<String> descriptions = getPointDescriptions(points.size());
int index = points.indexOf(new LatLon(avoidRoadInfo.lat, avoidRoadInfo.lon));
if (index != -1) {
roadIds.set(index, avoidRoadInfo.id);
descriptions.set(index, PointDescription.serializeToString(new PointDescription("", avoidRoadInfo.name)));
return savePoints(points, descriptions) && saveRoadIds(roadIds);
}
return false;
}
public List<Long> getRoadIds(int size) {
List<Long> list = new ArrayList<>();
String roadIds = settingsAPI.getString(globalPreferences, roadsIdsKey, "");
if (roadIds.trim().length() > 0) {
StringTokenizer tok = new StringTokenizer(roadIds, ",");
while (tok.hasMoreTokens() && list.size() <= size) {
String token = tok.nextToken();
list.add(Long.parseLong(token));
}
}
while (list.size() < size) {
list.add(0L);
}
return list;
}
@Override
public boolean deletePoint(int index) {
List<LatLon> points = getPoints();
List<Long> roadIds = getRoadIds(points.size());
List<String> descriptions = getPointDescriptions(points.size());
if (index < points.size()) {
points.remove(index);
roadIds.remove(index);
descriptions.remove(index);
return savePoints(points, descriptions) && saveRoadIds(roadIds);
}
return false;
}
@Override
public boolean deletePoint(LatLon latLon) {
List<LatLon> points = getPoints();
List<String> descriptions = getPointDescriptions(points.size());
List<Long> roadIds = getRoadIds(points.size());
int index = points.indexOf(latLon);
if (index != -1) {
points.remove(index);
roadIds.remove(index);
descriptions.remove(index);
return savePoints(points, descriptions) && saveRoadIds(roadIds);
}
return false;
}
@Override
public boolean movePoint(LatLon latLonEx, LatLon latLonNew) {
List<LatLon> points = getPoints();
List<String> descriptions = getPointDescriptions(points.size());
List<Long> roadIds = getRoadIds(points.size());
int i = points.indexOf(latLonEx);
if (i != -1) {
points.set(i, latLonNew);
return savePoints(points, descriptions) && saveRoadIds(roadIds);
} else {
return false;
}
}
public boolean saveRoadIds(List<Long> roadIds) {
StringBuilder stringBuilder = new StringBuilder();
Iterator<Long> iterator = roadIds.iterator();
while (iterator.hasNext()) {
stringBuilder.append(iterator.next());
if (iterator.hasNext()) {
stringBuilder.append(",");
}
}
return settingsAPI.edit(globalPreferences)
.putString(roadsIdsKey, stringBuilder.toString())
.commit();
} }
} }
@ -2994,10 +3121,15 @@ public class OsmandSettings {
public List<AvoidRoadInfo> getImpassableRoadPoints() { public List<AvoidRoadInfo> getImpassableRoadPoints() {
return mImpassableRoadsStorage.getImpassableRoadsInfo(); return mImpassableRoadsStorage.getImpassableRoadsInfo();
} }
public boolean addImpassableRoad(AvoidRoadInfo avoidRoadInfo) { public boolean addImpassableRoad(AvoidRoadInfo avoidRoadInfo) {
return mImpassableRoadsStorage.addImpassableRoadInfo(avoidRoadInfo); return mImpassableRoadsStorage.addImpassableRoadInfo(avoidRoadInfo);
} }
public boolean updateImpassableRoadInfo(AvoidRoadInfo avoidRoadInfo) {
return mImpassableRoadsStorage.updateImpassableRoadInfo(avoidRoadInfo);
}
public boolean removeImpassableRoad(int index) { public boolean removeImpassableRoad(int index) {
return mImpassableRoadsStorage.deletePoint(index); return mImpassableRoadsStorage.deletePoint(index);
} }

View file

@ -67,17 +67,21 @@ public class AvoidSpecificRoads {
for (Map.Entry<LatLon, AvoidRoadInfo> entry : impassableRoads.entrySet()) { for (Map.Entry<LatLon, AvoidRoadInfo> entry : impassableRoads.entrySet()) {
if (force || entry.getValue().id == 0) { if (force || entry.getValue().id == 0) {
addImpassableRoad(null, entry.getKey(), false, true); addImpassableRoad(null, entry.getKey(), false, true);
} else {
for (RoutingConfiguration.Builder builder : app.getAllRoutingConfigs()) {
builder.addImpassableRoad(entry.getValue().id);
}
} }
} }
} }
private ArrayAdapter<LatLon> createAdapter(MapActivity mapActivity, boolean nightMode) { private ArrayAdapter<AvoidRoadInfo> createAdapter(MapActivity mapActivity, boolean nightMode) {
final ArrayList<LatLon> points = new ArrayList<>(impassableRoads.keySet()); final ArrayList<AvoidRoadInfo> points = new ArrayList<>(impassableRoads.values());
final LatLon mapLocation = mapActivity.getMapLocation(); final LatLon mapLocation = mapActivity.getMapLocation();
final LayoutInflater inflater = UiUtilities.getInflater(mapActivity, nightMode); final LayoutInflater inflater = UiUtilities.getInflater(mapActivity, nightMode);
Context themedContext = UiUtilities.getThemedContext(mapActivity, nightMode); Context themedContext = UiUtilities.getThemedContext(mapActivity, nightMode);
return new ArrayAdapter<LatLon>(themedContext, R.layout.waypoint_reached, R.id.title, points) { return new ArrayAdapter<AvoidRoadInfo>(themedContext, 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) {
@ -85,12 +89,15 @@ public class AvoidSpecificRoads {
if (v == null || v.findViewById(R.id.info_close) == null) { if (v == null || v.findViewById(R.id.info_close) == null) {
v = inflater.inflate(R.layout.waypoint_reached, parent, false); v = inflater.inflate(R.layout.waypoint_reached, parent, false);
} }
final LatLon item = getItem(position); final AvoidRoadInfo 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)) ((ImageView) v.findViewById(R.id.waypoint_icon))
.setImageDrawable(getIcon(R.drawable.ic_action_road_works_dark)); .setImageDrawable(getIcon(R.drawable.ic_action_road_works_dark));
((TextView) v.findViewById(R.id.waypoint_dist)).setText(getDist(mapLocation, item));
((TextView) v.findViewById(R.id.waypoint_text)).setText(getText(item)); LatLon latLon = item != null ? new LatLon(item.lat, item.lon) : null;
String name = item != null ? item.name : app.getString(R.string.shared_string_road);
((TextView) v.findViewById(R.id.waypoint_dist)).setText(getDist(mapLocation, latLon));
((TextView) v.findViewById(R.id.waypoint_text)).setText(name);
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(getIcon(R.drawable.ic_action_remove_dark)); remove.setImageDrawable(getIcon(R.drawable.ic_action_remove_dark));
@ -153,15 +160,15 @@ public class AvoidSpecificRoads {
public void removeImpassableRoad(LatLon latLon) { public void removeImpassableRoad(LatLon latLon) {
app.getSettings().removeImpassableRoad(latLon); app.getSettings().removeImpassableRoad(latLon);
RouteDataObject obj = impassableRoads.remove(latLon); AvoidRoadInfo obj = impassableRoads.remove(latLon);
if (obj != null) { if (obj != null) {
for (RoutingConfiguration.Builder builder : app.getAllRoutingConfigs()) { for (RoutingConfiguration.Builder builder : app.getAllRoutingConfigs()) {
builder.removeImpassableRoad(obj); builder.removeImpassableRoad(obj.id);
} }
} }
} }
public void removeImpassableRoad(RouteDataObject obj) { public void removeImpassableRoad(AvoidRoadInfo obj) {
removeImpassableRoad(getLocation(obj)); removeImpassableRoad(getLocation(obj));
} }
@ -174,13 +181,13 @@ public class AvoidSpecificRoads {
if (impassableRoads.isEmpty()) { if (impassableRoads.isEmpty()) {
bld.setMessage(R.string.avoid_roads_msg); bld.setMessage(R.string.avoid_roads_msg);
} else { } else {
final ArrayAdapter<LatLon> listAdapter = createAdapter(mapActivity, nightMode); final ArrayAdapter<AvoidRoadInfo> listAdapter = createAdapter(mapActivity, nightMode);
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) {
LatLon point = listAdapter.getItem(which); AvoidRoadInfo point = listAdapter.getItem(which);
if (point != null) { if (point != null) {
showOnMap(mapActivity, point.getLatitude(), point.getLongitude(), getText(point)); showOnMap(mapActivity, point.lat, point.lon, point.name);
} }
dialog.dismiss(); dialog.dismiss();
} }
@ -228,9 +235,12 @@ public class AvoidSpecificRoads {
LatLon newLoc = new LatLon(MapUtils.get31LatitudeY((int) point.y), MapUtils.get31LongitudeX((int) point.x)); LatLon newLoc = new LatLon(MapUtils.get31LatitudeY((int) point.y), MapUtils.get31LongitudeX((int) point.x));
ll.setLatitude(newLoc.getLatitude()); ll.setLatitude(newLoc.getLatitude());
ll.setLongitude(newLoc.getLongitude()); ll.setLongitude(newLoc.getLongitude());
addImpassableRoadInternal(roads.get(searchResult.getRoadIndex()).getObject(), ll, showDialog, mapActivity, newLoc);
RouteDataObject object = roads.get(searchResult.getRoadIndex()).getObject();
AvoidRoadInfo avoidRoadInfo = getAvoidRoadInfoForDataObject(object, newLoc.getLatitude(), newLoc.getLongitude());
addImpassableRoadInternal(avoidRoadInfo, showDialog, mapActivity, newLoc);
if (!skipWritingSettings) { if (!skipWritingSettings) {
app.getSettings().addImpassableRoad(newLoc.getLatitude(), newLoc.getLongitude()); app.getSettings().addImpassableRoad(avoidRoadInfo);
} }
return; return;
} }
@ -244,7 +254,8 @@ public class AvoidSpecificRoads {
Toast.makeText(mapActivity, R.string.error_avoid_specific_road, Toast.LENGTH_LONG).show(); Toast.makeText(mapActivity, R.string.error_avoid_specific_road, Toast.LENGTH_LONG).show();
} }
} else { } else {
addImpassableRoadInternal(object, ll, showDialog, mapActivity, loc); AvoidRoadInfo avoidRoadInfo = getAvoidRoadInfoForDataObject(object, ll.getLatitude(), ll.getLongitude());
addImpassableRoadInternal(avoidRoadInfo, showDialog, mapActivity, loc);
} }
return true; return true;
} }
@ -256,12 +267,13 @@ public class AvoidSpecificRoads {
}); });
if (!skipWritingSettings) { if (!skipWritingSettings) {
app.getSettings().addImpassableRoad(loc.getLatitude(), loc.getLongitude()); AvoidRoadInfo avoidRoadInfo = getAvoidRoadInfoForDataObject(null, loc.getLatitude(), loc.getLongitude());
app.getSettings().addImpassableRoad(avoidRoadInfo);
} }
} }
public void replaceImpassableRoad(final MapActivity activity, public void replaceImpassableRoad(final MapActivity activity,
final RouteDataObject currentObject, final AvoidRoadInfo currentObject,
final LatLon newLoc, final LatLon newLoc,
final boolean showDialog, final boolean showDialog,
final AvoidSpecificRoadsCallback callback) { final AvoidSpecificRoadsCallback callback) {
@ -284,12 +296,13 @@ public class AvoidSpecificRoads {
app.getSettings().moveImpassableRoad(oldLoc, newLoc); app.getSettings().moveImpassableRoad(oldLoc, newLoc);
impassableRoads.remove(oldLoc); impassableRoads.remove(oldLoc);
for (RoutingConfiguration.Builder builder : app.getAllRoutingConfigs()) { for (RoutingConfiguration.Builder builder : app.getAllRoutingConfigs()) {
builder.removeImpassableRoad(currentObject); builder.removeImpassableRoad(currentObject.id);
} }
addImpassableRoadInternal(object, ll, showDialog, activity, newLoc); AvoidRoadInfo avoidRoadInfo = getAvoidRoadInfoForDataObject(object, newLoc.getLatitude(), newLoc.getLongitude());
addImpassableRoadInternal(avoidRoadInfo, showDialog, activity, newLoc);
if (callback != null) { if (callback != null) {
callback.onAddImpassableRoad(true, object); callback.onAddImpassableRoad(true, avoidRoadInfo);
} }
} }
return true; return true;
@ -302,19 +315,19 @@ public class AvoidSpecificRoads {
}); });
} }
private void addImpassableRoadInternal(@NonNull RouteDataObject object, private void addImpassableRoadInternal(@NonNull AvoidRoadInfo avoidRoadInfo,
@NonNull Location ll,
boolean showDialog, boolean showDialog,
@Nullable MapActivity activity, @Nullable MapActivity activity,
@NonNull LatLon loc) { @NonNull LatLon loc) {
boolean roadAdded = false; boolean roadAdded = false;
for (RoutingConfiguration.Builder builder : app.getAllRoutingConfigs()) { for (RoutingConfiguration.Builder builder : app.getAllRoutingConfigs()) {
roadAdded |= builder.addImpassableRoad(object, ll); roadAdded |= builder.addImpassableRoad(avoidRoadInfo.id);
} }
if (roadAdded) { if (roadAdded) {
impassableRoads.put(loc, object); app.getSettings().updateImpassableRoadInfo(avoidRoadInfo);
impassableRoads.put(loc, avoidRoadInfo);
} else { } else {
LatLon location = getLocation(object); LatLon location = getLocation(avoidRoadInfo);
if (location != null) { if (location != null) {
app.getSettings().removeImpassableRoad(location); app.getSettings().removeImpassableRoad(location);
} }
@ -355,8 +368,11 @@ public class AvoidSpecificRoads {
boolean isCancelled(); boolean isCancelled();
} }
private AvoidRoadInfo createAvoidRoadInfo(@Nullable RouteDataObject object, double lat, double lon) { private AvoidRoadInfo getAvoidRoadInfoForDataObject(@Nullable RouteDataObject object, double lat, double lon) {
AvoidRoadInfo avoidRoadInfo = new AvoidRoadInfo(); AvoidRoadInfo avoidRoadInfo = impassableRoads.get(new LatLon(lat, lon));
if (avoidRoadInfo == null) {
avoidRoadInfo = new AvoidRoadInfo();
}
avoidRoadInfo.id = object != null ? object.id : 0; avoidRoadInfo.id = object != null ? object.id : 0;
avoidRoadInfo.lat = lat; avoidRoadInfo.lat = lat;
avoidRoadInfo.lon = lon; avoidRoadInfo.lon = lon;