Draw transport route with colors

This commit is contained in:
crimean 2018-11-25 18:41:49 +03:00
parent f399119723
commit b1152c4271
3 changed files with 134 additions and 44 deletions

View file

@ -936,6 +936,7 @@ public class RoutingHelper {
} }
public void recalculateRouteDueToSettingsChange() { public void recalculateRouteDueToSettingsChange() {
clearCurrentRoute(finalLocation, intermediatePoints);
if (isPublicTransportMode()) { if (isPublicTransportMode()) {
Location start = lastFixedLocation; Location start = lastFixedLocation;
LatLon finish = finalLocation; LatLon finish = finalLocation;
@ -946,7 +947,6 @@ public class RoutingHelper {
transportRoutingHelper.recalculateRouteDueToSettingsChange(); transportRoutingHelper.recalculateRouteDueToSettingsChange();
} }
} else { } else {
clearCurrentRoute(finalLocation, intermediatePoints);
recalculateRouteInBackground(lastFixedLocation, finalLocation, intermediatePoints, currentGPXRoute, route, true, false); recalculateRouteInBackground(lastFixedLocation, finalLocation, intermediatePoints, currentGPXRoute, route, true, false);
} }
} }

View file

@ -13,6 +13,7 @@ import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.util.Pair;
import android.view.MotionEvent; import android.view.MotionEvent;
import net.osmand.binary.BinaryMapIndexReader; import net.osmand.binary.BinaryMapIndexReader;
@ -137,14 +138,25 @@ public abstract class OsmandMapLayer {
return x >= lx && x <= rx && y >= ty && y <= by; return x >= lx && x <= rx && y >= ty && y <= by;
} }
public int calculatePath(RotatedTileBox tb, TIntArrayList xs, TIntArrayList ys, Path path) { public int calculatePath(RotatedTileBox tb, TIntArrayList xs, TIntArrayList ys, Path path) {
List<Pair<Path, Integer>> paths = new ArrayList<>();
int res = calculatePath(tb, xs, ys, null, paths);
if (paths.size() > 0) {
path.addPath(paths.get(0).first);
}
return res;
}
public int calculatePath(RotatedTileBox tb, TIntArrayList xs, TIntArrayList ys, List<Integer> colors, List<Pair<Path, Integer>> paths) {
boolean segmentStarted = false; boolean segmentStarted = false;
int prevX = xs.get(0); int prevX = xs.get(0);
int prevY = ys.get(0); int prevY = ys.get(0);
int height = tb.getPixHeight(); int height = tb.getPixHeight();
int width = tb.getPixWidth(); int width = tb.getPixWidth();
int cnt = 0; int cnt = 0;
boolean hasColors = colors != null && colors.size() == xs.size();
int color = hasColors ? colors.get(0) : 0;
Path path = new Path();
boolean prevIn = isIn(prevX, prevY, 0, 0, width, height); boolean prevIn = isIn(prevX, prevY, 0, 0, width, height);
for (int i = 1; i < xs.size(); i++) { for (int i = 1; i < xs.size(); i++) {
int currX = xs.get(i); int currX = xs.get(i);
@ -186,6 +198,21 @@ public abstract class OsmandMapLayer {
prevIn = currIn; prevIn = currIn;
prevX = currX; prevX = currX;
prevY = currY; prevY = currY;
if (hasColors) {
int newColor = colors.get(i);
if (color != newColor) {
paths.add(new Pair<>(path, color));
path = new Path();
if (segmentStarted) {
path.moveTo(currX, currY);
}
color = newColor;
}
}
}
if (!path.isEmpty()) {
paths.add(new Pair<>(path, color));
} }
return cnt; return cnt;
} }
@ -383,6 +410,8 @@ public abstract class OsmandMapLayer {
protected static class RenderingLineAttributes { protected static class RenderingLineAttributes {
protected int cachedHash; protected int cachedHash;
public Paint paint; public Paint paint;
public Paint customColorPaint;
public int customColor = 0;
public int defaultWidth = 0; public int defaultWidth = 0;
public int defaultColor = 0; public int defaultColor = 0;
public boolean isPaint2; public boolean isPaint2;
@ -402,6 +431,7 @@ public abstract class OsmandMapLayer {
public RenderingLineAttributes(String renderingAttribute) { public RenderingLineAttributes(String renderingAttribute) {
this.renderingAttribute = renderingAttribute; this.renderingAttribute = renderingAttribute;
paint = initPaint(); paint = initPaint();
customColorPaint = new Paint(paint);
paint2 = initPaint(); paint2 = initPaint();
paint3 = initPaint(); paint3 = initPaint();
paint_1 = initPaint(); paint_1 = initPaint();
@ -462,6 +492,7 @@ public abstract class OsmandMapLayer {
if (paint.getStrokeWidth() == 0 && defaultWidth != 0) { if (paint.getStrokeWidth() == 0 && defaultWidth != 0) {
paint.setStrokeWidth(defaultWidth); paint.setStrokeWidth(defaultWidth);
} }
customColorPaint = new Paint(paint);
} }
return true; return true;
} }
@ -486,7 +517,12 @@ public abstract class OsmandMapLayer {
if (isShadowPaint) { if (isShadowPaint) {
canvas.drawPath(path, shadowPaint); canvas.drawPath(path, shadowPaint);
} }
canvas.drawPath(path, paint); if (customColor != 0) {
customColorPaint.setColor(customColor);
canvas.drawPath(path, customColorPaint);
} else {
canvas.drawPath(path, paint);
}
if (isPaint2) { if (isPaint2) {
canvas.drawPath(path, paint2); canvas.drawPath(path, paint2);
} }

View file

@ -12,11 +12,13 @@ import android.graphics.PointF;
import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.support.annotation.ColorInt; import android.support.annotation.ColorInt;
import android.util.Pair;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.QuadRect; import net.osmand.data.QuadRect;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
import net.osmand.data.TransportRoute;
import net.osmand.osm.edit.Node; import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.OSMSettings; import net.osmand.osm.edit.OSMSettings;
import net.osmand.osm.edit.Way; import net.osmand.osm.edit.Way;
@ -28,12 +30,14 @@ import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.TransportRoutingHelper; import net.osmand.plus.routing.TransportRoutingHelper;
import net.osmand.router.TransportRoutePlanner; import net.osmand.plus.transport.TransportStopRoute;
import net.osmand.plus.transport.TransportStopType;
import net.osmand.router.TransportRoutePlanner.TransportRouteResult; import net.osmand.router.TransportRoutePlanner.TransportRouteResult;
import net.osmand.router.TransportRoutePlanner.TransportRouteResultSegment; import net.osmand.router.TransportRoutePlanner.TransportRouteResultSegment;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -53,8 +57,6 @@ public class RouteLayer extends OsmandMapLayer {
// keep array lists created // keep array lists created
private List<Location> actionPoints = new ArrayList<Location>(); private List<Location> actionPoints = new ArrayList<Location>();
private Path path;
// cache // cache
private Bitmap coloredArrowUp; private Bitmap coloredArrowUp;
private Bitmap actionArrow; private Bitmap actionArrow;
@ -69,6 +71,7 @@ public class RouteLayer extends OsmandMapLayer {
private TrackChartPoints trackChartPoints; private TrackChartPoints trackChartPoints;
private RenderingLineAttributes attrs; private RenderingLineAttributes attrs;
private boolean nightMode;
public RouteLayer(RoutingHelper helper) { public RouteLayer(RoutingHelper helper) {
@ -82,8 +85,7 @@ public class RouteLayer extends OsmandMapLayer {
private void initUI() { private void initUI() {
actionArrow = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_action_arrow, null); actionArrow = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_action_arrow, null);
path = new Path();
paintIcon = new Paint(); paintIcon = new Paint();
paintIcon.setFilterBitmap(true); paintIcon.setFilterBitmap(true);
paintIcon.setAntiAlias(true); paintIcon.setAntiAlias(true);
@ -189,6 +191,7 @@ public class RouteLayer extends OsmandMapLayer {
paintIconAction.setColorFilter(new PorterDuffColorFilter(attrs.paint3.getColor(), Mode.MULTIPLY)); paintIconAction.setColorFilter(new PorterDuffColorFilter(attrs.paint3.getColor(), Mode.MULTIPLY));
paintIcon.setColorFilter(new PorterDuffColorFilter(attrs.paint2.getColor(), Mode.MULTIPLY)); paintIcon.setColorFilter(new PorterDuffColorFilter(attrs.paint2.getColor(), Mode.MULTIPLY));
} }
nightMode = settings != null && settings.isNightMode();
} }
private void drawXAxisPoints(Canvas canvas, RotatedTileBox tileBox) { private void drawXAxisPoints(Canvas canvas, RotatedTileBox tileBox) {
@ -427,14 +430,27 @@ public class RouteLayer extends OsmandMapLayer {
TransportRouteResult transportRoute; TransportRouteResult transportRoute;
double mapDensity; double mapDensity;
TreeMap<Integer, RouteGeometryZoom> zooms = new TreeMap<>(); TreeMap<Integer, RouteGeometryZoom> zooms = new TreeMap<>();
List<Location> locations = Collections.emptyList(); List<Location> locations = Collections.emptyList();
TreeMap<Integer, Integer> colorsMap = new TreeMap<>();
// cache arrays // cache arrays
TIntArrayList tx = new TIntArrayList(); TIntArrayList tx = new TIntArrayList();
TIntArrayList ty = new TIntArrayList(); TIntArrayList ty = new TIntArrayList();
List<Double> angles = new ArrayList<>(); List<Double> angles = new ArrayList<>();
List<Double> distances = new ArrayList<>(); List<Double> distances = new ArrayList<>();
List<Integer> colors = new ArrayList<>();
private int getColor(int index) {
List<Integer> list = new ArrayList<>(colorsMap.keySet());
for (int i = list.size() -1; i >= 0; i--) {
int c = list.get(i);
if (c <= index) {
return colorsMap.get(c);
}
}
return attrs.paint.getColor();
}
public void updateRoute(RotatedTileBox tb, RouteCalculationResult route) { public void updateRoute(RotatedTileBox tb, RouteCalculationResult route) {
if(tb.getMapDensity() != mapDensity || this.route != route) { if(tb.getMapDensity() != mapDensity || this.route != route) {
this.route = route; this.route = route;
@ -443,6 +459,7 @@ public class RouteLayer extends OsmandMapLayer {
} else { } else {
locations = route.getImmutableAllLocations(); locations = route.getImmutableAllLocations();
} }
colorsMap.clear();
this.mapDensity = tb.getMapDensity(); this.mapDensity = tb.getMapDensity();
zooms.clear(); zooms.clear();
} }
@ -453,25 +470,35 @@ public class RouteLayer extends OsmandMapLayer {
this.transportRoute = route; this.transportRoute = route;
if (route == null) { if (route == null) {
locations = Collections.emptyList(); locations = Collections.emptyList();
colorsMap.clear();
} else { } else {
LatLon start = transportHelper.getStartLocation(); LatLon start = transportHelper.getStartLocation();
LatLon end = transportHelper.getEndLocation(); LatLon end = transportHelper.getEndLocation();
List<Way> list = new ArrayList<>(); List<Way> list = new ArrayList<>();
calculateTransportResult(start, end, route, list); List<Integer> cols = new ArrayList<>();
calculateTransportResult(start, end, route, list, cols);
List<Location> locs = new ArrayList<>(); List<Location> locs = new ArrayList<>();
for (Way w : list) { TreeMap<Integer, Integer> colsMap = new TreeMap<>();
//Location loc = new Location("transport"); int i = 0;
//loc.setLatitude(w.getLatitude()); int k = 0;
//loc.setLongitude(w.getLongitude()); if (list.size() > 0) {
//locs.add(loc); for (Way w : list) {
for (Node n : w.getNodes()) { colsMap.put(k, cols.get(i++));
Location ln = new Location("transport"); //Location loc = new Location("");
ln.setLatitude(n.getLatitude()); //loc.setLatitude(w.getLatitude());
ln.setLongitude(n.getLongitude()); //loc.setLongitude(w.getLongitude());
locs.add(ln); //locs.add(loc);
for (Node n : w.getNodes()) {
Location ln = new Location("");
ln.setLatitude(n.getLatitude());
ln.setLongitude(n.getLongitude());
locs.add(ln);
k++;
}
} }
} }
locations = locs; locations = locs;
colorsMap = colsMap;
} }
this.mapDensity = tb.getMapDensity(); this.mapDensity = tb.getMapDensity();
zooms.clear(); zooms.clear();
@ -494,14 +521,13 @@ public class RouteLayer extends OsmandMapLayer {
TByteArrayList simplification = geometryZoom.getSimplifyPoints(); TByteArrayList simplification = geometryZoom.getSimplifyPoints();
List<Double> odistances = geometryZoom.getDistances(); List<Double> odistances = geometryZoom.getDistances();
clearArrays(); clearArrays();
int color = attrs.paint.getColor();
boolean previousVisible = false; boolean previousVisible = false;
if (lastProjection != null) { if (lastProjection != null) {
if (leftLongitude <= lastProjection.getLongitude() && lastProjection.getLongitude() <= rightLongitude if (leftLongitude <= lastProjection.getLongitude() && lastProjection.getLongitude() <= rightLongitude
&& bottomLatitude <= lastProjection.getLatitude() && lastProjection.getLatitude() <= topLatitude) { && bottomLatitude <= lastProjection.getLatitude() && lastProjection.getLatitude() <= topLatitude) {
addLocation(tb, lastProjection, tx, ty, angles, distances, 0); addLocation(tb, lastProjection, color, tx, ty, angles, distances, 0, colors);
previousVisible = true; previousVisible = true;
} }
} }
@ -509,7 +535,8 @@ public class RouteLayer extends OsmandMapLayer {
int previous = -1; int previous = -1;
for (int i = currentRoute; i < routeNodes.size(); i++) { for (int i = currentRoute; i < routeNodes.size(); i++) {
Location ls = routeNodes.get(i); Location ls = routeNodes.get(i);
if(simplification.getQuick(i) == 0) { color = getColor(i);
if (simplification.getQuick(i) == 0 && !colorsMap.containsKey(i)) {
continue; continue;
} }
if (leftLongitude <= ls.getLongitude() && ls.getLongitude() <= rightLongitude && bottomLatitude <= ls.getLatitude() if (leftLongitude <= ls.getLongitude() && ls.getLongitude() <= rightLongitude && bottomLatitude <= ls.getLatitude()
@ -523,23 +550,23 @@ public class RouteLayer extends OsmandMapLayer {
} else if (lastProjection != null) { } else if (lastProjection != null) {
lt = lastProjection; lt = lastProjection;
} }
addLocation(tb, lt, tx, ty, angles, distances, 0); // first point addLocation(tb, lt, color, tx, ty, angles, distances, 0, colors); // first point
} }
addLocation(tb, ls, tx, ty, angles, distances, dist); addLocation(tb, ls, color, tx, ty, angles, distances, dist, colors);
previousVisible = true; previousVisible = true;
} else if (previousVisible) { } else if (previousVisible) {
addLocation(tb, ls, tx, ty, angles, distances, previous == -1 ? 0 : odistances.get(i)); addLocation(tb, ls, color, tx, ty, angles, distances, previous == -1 ? 0 : odistances.get(i), colors);
double distToFinish = 0; double distToFinish = 0;
for(int ki = i + 1; ki < odistances.size(); ki++) { for(int ki = i + 1; ki < odistances.size(); ki++) {
distToFinish += odistances.get(ki); distToFinish += odistances.get(ki);
} }
drawRouteSegment(tb, canvas, tx, ty, angles, distances, distToFinish); drawRouteSegment(tb, canvas, tx, ty, angles, distances, distToFinish, colors);
previousVisible = false; previousVisible = false;
clearArrays(); clearArrays();
} }
previous = i; previous = i;
} }
drawRouteSegment(tb, canvas, tx, ty, angles, distances, 0); drawRouteSegment(tb, canvas, tx, ty, angles, distances, 0, colors);
} }
private void clearArrays() { private void clearArrays() {
@ -547,10 +574,11 @@ public class RouteLayer extends OsmandMapLayer {
ty.clear(); ty.clear();
distances.clear(); distances.clear();
angles.clear(); angles.clear();
colors.clear();
} }
private void addLocation(RotatedTileBox tb, Location ls, TIntArrayList tx, TIntArrayList ty, private void addLocation(RotatedTileBox tb, Location ls, int color, TIntArrayList tx, TIntArrayList ty,
List<Double> angles, List<Double> distances, double dist) { List<Double> angles, List<Double> distances, double dist, List<Integer> colors) {
float x = tb.getPixXFromLatLon(ls.getLatitude(), ls.getLongitude()); float x = tb.getPixXFromLatLon(ls.getLatitude(), ls.getLongitude());
float y = tb.getPixYFromLatLon(ls.getLatitude(), ls.getLongitude()); float y = tb.getPixYFromLatLon(ls.getLatitude(), ls.getLongitude());
float px = x; float px = x;
@ -573,21 +601,26 @@ public class RouteLayer extends OsmandMapLayer {
ty.add((int) y); ty.add((int) y);
angles.add(angle); angles.add(angle);
distances.add(distSegment); distances.add(distSegment);
colors.add(color);
} }
} }
RouteSimplificationGeometry routeGeometry = new RouteSimplificationGeometry(); RouteSimplificationGeometry routeGeometry = new RouteSimplificationGeometry();
private void drawRouteSegment(RotatedTileBox tb, Canvas canvas, TIntArrayList tx, TIntArrayList ty, private void drawRouteSegment(RotatedTileBox tb, Canvas canvas, TIntArrayList tx, TIntArrayList ty,
List<Double> angles, List<Double> distances, double distToFinish) { List<Double> angles, List<Double> distances, double distToFinish, List<Integer> colors) {
if(tx.size() < 2) { if (tx.size() < 2) {
return; return;
} }
try { try {
path.reset(); List<Pair<Path, Integer>> paths = new ArrayList<>();
canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY()); canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY());
calculatePath(tb, tx, ty, path); calculatePath(tb, tx, ty, colors, paths);
attrs.drawPath(canvas, path); for (Pair<Path, Integer> pc : paths) {
attrs.customColor = pc.second;
attrs.drawPath(canvas, pc.first);
}
attrs.customColor = 0;
if (tb.getZoomAnimation() == 0) { if (tb.getZoomAnimation() == 0) {
drawArrowsOverPath(canvas, tb, tx, ty, angles, distances, coloredArrowUp, distToFinish); drawArrowsOverPath(canvas, tb, tx, ty, angles, distances, coloredArrowUp, distToFinish);
} }
@ -768,21 +801,22 @@ public class RouteLayer extends OsmandMapLayer {
return false; return false;
} }
private void calculateTransportResult(LatLon start, LatLon end, TransportRouteResult r, List<Way> res, List<Integer> colors) {
private void calculateTransportResult(LatLon start, LatLon end, TransportRouteResult r, List<Way> res) {
if (r != null) { if (r != null) {
LatLon p = start; LatLon p = start;
for (TransportRouteResultSegment s : r.getSegments()) { for (TransportRouteResultSegment s : r.getSegments()) {
LatLon floc = s.getStart().getLocation(); LatLon floc = s.getStart().getLocation();
addWalk(res, p, floc); addRouteWalk(p, floc, res, colors);
res.addAll(s.getGeometry()); List<Way> geometry = s.getGeometry();
res.addAll(geometry);
addColors(s.route, geometry.size(), colors);
p = s.getEnd().getLocation(); p = s.getEnd().getLocation();
} }
addWalk(res, p, end); addRouteWalk(p, end, res, colors);
} }
} }
private void addWalk(List<Way> res, LatLon s, LatLon e) { private void addRouteWalk(LatLon s, LatLon e, List<Way> res, List<Integer> colors) {
double dist = MapUtils.getDistance(s, e); double dist = MapUtils.getDistance(s, e);
if (dist > 50) { if (dist > 50) {
Way way = new Way(-1); Way way = new Way(-1);
@ -790,6 +824,26 @@ public class RouteLayer extends OsmandMapLayer {
way.addNode(new Node(s.getLatitude(), s.getLongitude(), -1)); way.addNode(new Node(s.getLatitude(), s.getLongitude(), -1));
way.addNode(new Node(e.getLatitude(), e.getLongitude(), -1)); way.addNode(new Node(e.getLatitude(), e.getLongitude(), -1));
res.add(way); res.add(way);
addColors(null, 1, colors);
} }
} }
private void addColors(TransportRoute route, int count, List<Integer> colors) {
int color;
if (route == null) {
color = attrs.paint.getColor();
} else {
TransportStopRoute r = new TransportStopRoute();
r.type = TransportStopType.findType(route.getType());
r.route = route;
color = r.getColor(helper.getApplication(), nightMode);
}
addColors(color, count, colors);
}
private void addColors(int color, int count, List<Integer> colors) {
Integer[] integers = new Integer[count];
Arrays.fill(integers, color);
colors.addAll(Arrays.asList(integers));
}
} }