Add gradient route line
This commit is contained in:
parent
26f9e85f2a
commit
ff7aa932a3
5 changed files with 269 additions and 54 deletions
|
@ -186,7 +186,7 @@ public class RouteColorize {
|
||||||
public List<RouteColorizationPoint> getResult(boolean simplify) {
|
public List<RouteColorizationPoint> getResult(boolean simplify) {
|
||||||
List<RouteColorizationPoint> result = new ArrayList<>();
|
List<RouteColorizationPoint> result = new ArrayList<>();
|
||||||
if (simplify) {
|
if (simplify) {
|
||||||
result = simplify();
|
result = simplify(zoom);
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < latitudes.length; i++) {
|
for (int i = 0; i < latitudes.length; i++) {
|
||||||
result.add(new RouteColorizationPoint(i, latitudes[i], longitudes[i], values[i]));
|
result.add(new RouteColorizationPoint(i, latitudes[i], longitudes[i], values[i]));
|
||||||
|
@ -242,7 +242,7 @@ public class RouteColorize {
|
||||||
return rgbaToDecimal(0, 0, 0, 0);
|
return rgbaToDecimal(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<RouteColorizationPoint> simplify() {
|
public List<RouteColorizationPoint> simplify(int zoom) {
|
||||||
if (dataList == null) {
|
if (dataList == null) {
|
||||||
dataList = new ArrayList<>();
|
dataList = new ArrayList<>();
|
||||||
for (int i = 0; i < latitudes.length; i++) {
|
for (int i = 0; i < latitudes.length; i++) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.LinearGradient;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Paint.Cap;
|
import android.graphics.Paint.Cap;
|
||||||
|
@ -11,6 +12,7 @@ import android.graphics.Path;
|
||||||
import android.graphics.PointF;
|
import android.graphics.PointF;
|
||||||
import android.graphics.PorterDuff.Mode;
|
import android.graphics.PorterDuff.Mode;
|
||||||
import android.graphics.PorterDuffColorFilter;
|
import android.graphics.PorterDuffColorFilter;
|
||||||
|
import android.graphics.Shader;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.LayerDrawable;
|
import android.graphics.drawable.LayerDrawable;
|
||||||
|
|
||||||
|
@ -44,6 +46,7 @@ import net.osmand.plus.routing.RouteService;
|
||||||
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.plus.settings.backend.CommonPreference;
|
import net.osmand.plus.settings.backend.CommonPreference;
|
||||||
|
import net.osmand.plus.track.GradientScaleType;
|
||||||
import net.osmand.plus.views.OsmandMapLayer;
|
import net.osmand.plus.views.OsmandMapLayer;
|
||||||
import net.osmand.plus.views.OsmandMapTileView;
|
import net.osmand.plus.views.OsmandMapTileView;
|
||||||
import net.osmand.plus.views.layers.ContextMenuLayer.IContextMenuProvider;
|
import net.osmand.plus.views.layers.ContextMenuLayer.IContextMenuProvider;
|
||||||
|
@ -54,6 +57,7 @@ import net.osmand.plus.views.layers.geometry.RouteGeometryWayContext;
|
||||||
import net.osmand.render.RenderingRuleProperty;
|
import net.osmand.render.RenderingRuleProperty;
|
||||||
import net.osmand.render.RenderingRuleSearchRequest;
|
import net.osmand.render.RenderingRuleSearchRequest;
|
||||||
import net.osmand.render.RenderingRulesStorage;
|
import net.osmand.render.RenderingRulesStorage;
|
||||||
|
import net.osmand.router.RouteColorize;
|
||||||
import net.osmand.router.TransportRouteResult;
|
import net.osmand.router.TransportRouteResult;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
import net.osmand.util.MapUtils;
|
import net.osmand.util.MapUtils;
|
||||||
|
@ -109,6 +113,7 @@ public class RouteLayer extends OsmandMapLayer implements IContextMenuProvider {
|
||||||
|
|
||||||
private int routeLineColor;
|
private int routeLineColor;
|
||||||
private Integer directionArrowsColor;
|
private Integer directionArrowsColor;
|
||||||
|
private GradientScaleType gradientScaleType = null;
|
||||||
|
|
||||||
public RouteLayer(RoutingHelper helper) {
|
public RouteLayer(RoutingHelper helper) {
|
||||||
this.helper = helper;
|
this.helper = helper;
|
||||||
|
@ -331,14 +336,22 @@ public class RouteLayer extends OsmandMapLayer implements IContextMenuProvider {
|
||||||
DrawSettings settings,
|
DrawSettings settings,
|
||||||
RouteLineDrawInfo drawInfo) {
|
RouteLineDrawInfo drawInfo) {
|
||||||
updateAttrs(settings, tileBox);
|
updateAttrs(settings, tileBox);
|
||||||
updateRouteColors(nightMode);
|
|
||||||
paintRouteLinePreview.setColor(getRouteLineColor());
|
|
||||||
paintRouteLinePreview.setStrokeWidth(getRouteLineWidth(tileBox));
|
paintRouteLinePreview.setStrokeWidth(getRouteLineWidth(tileBox));
|
||||||
|
|
||||||
int centerX = drawInfo.getCenterX();
|
int centerX = drawInfo.getCenterX();
|
||||||
int centerY = drawInfo.getCenterY();
|
int centerY = drawInfo.getCenterY();
|
||||||
int screenHeight = drawInfo.getScreenHeight();
|
int screenHeight = drawInfo.getScreenHeight();
|
||||||
|
|
||||||
|
if (gradientScaleType == GradientScaleType.ALTITUDE || gradientScaleType == GradientScaleType.SLOPE) {
|
||||||
|
int[] colors = new int[] {RouteColorize.RED, RouteColorize.YELLOW, RouteColorize.GREEN};
|
||||||
|
float[] positions = new float[] {0, 0.5f, 1};
|
||||||
|
LinearGradient gradient = new LinearGradient(centerX, 0, centerX, screenHeight, colors, positions, Shader.TileMode.CLAMP);
|
||||||
|
paintRouteLinePreview.setShader(gradient);
|
||||||
|
} else {
|
||||||
|
updateRouteColors(nightMode);
|
||||||
|
paintRouteLinePreview.setColor(getRouteLineColor());
|
||||||
|
}
|
||||||
|
|
||||||
canvas.drawLine(centerX, 0, centerX, screenHeight, paintRouteLinePreview);
|
canvas.drawLine(centerX, 0, centerX, screenHeight, paintRouteLinePreview);
|
||||||
|
|
||||||
if (previewIcon == null) {
|
if (previewIcon == null) {
|
||||||
|
@ -524,9 +537,9 @@ public class RouteLayer extends OsmandMapLayer implements IContextMenuProvider {
|
||||||
boolean directTo = route.getRouteService() == RouteService.DIRECT_TO;
|
boolean directTo = route.getRouteService() == RouteService.DIRECT_TO;
|
||||||
boolean straight = route.getRouteService() == RouteService.STRAIGHT;
|
boolean straight = route.getRouteService() == RouteService.STRAIGHT;
|
||||||
publicTransportRouteGeometry.clearRoute();
|
publicTransportRouteGeometry.clearRoute();
|
||||||
routeGeometry.updateRoute(tb, route);
|
routeGeometry.setRouteStyleParams(getRouteLineColor(), getRouteLineWidth(tb), getDirectionArrowsColor(), gradientScaleType);
|
||||||
|
routeGeometry.updateRoute(tb, route, view.getApplication());
|
||||||
updateRouteColors(nightMode);
|
updateRouteColors(nightMode);
|
||||||
routeGeometry.setRouteStyleParams(getRouteLineColor(), getRouteLineWidth(tb), getDirectionArrowsColor());
|
|
||||||
if (directTo) {
|
if (directTo) {
|
||||||
routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude,
|
routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude,
|
||||||
null, 0);
|
null, 0);
|
||||||
|
|
|
@ -126,7 +126,7 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
zooms.clear();
|
zooms.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private PathGeometryZoom getGeometryZoom(RotatedTileBox tb) {
|
protected PathGeometryZoom getGeometryZoom(RotatedTileBox tb, Map<Integer, PathGeometryZoom> zooms) {
|
||||||
int zoom = tb.getZoom();
|
int zoom = tb.getZoom();
|
||||||
PathGeometryZoom zm = zooms.size() > zoom ? zooms.get(zoom) : null;
|
PathGeometryZoom zm = zooms.size() > zoom ? zooms.get(zoom) : null;
|
||||||
if (zm == null) {
|
if (zm == null) {
|
||||||
|
@ -148,7 +148,7 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
if (locationProvider == null || locationProvider.getSize() == 0) {
|
if (locationProvider == null || locationProvider.getSize() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PathGeometryZoom geometryZoom = getGeometryZoom(tb);
|
PathGeometryZoom geometryZoom = getGeometryZoom(tb, zooms);
|
||||||
TByteArrayList simplification = geometryZoom.getSimplifyPoints();
|
TByteArrayList simplification = geometryZoom.getSimplifyPoints();
|
||||||
List<Double> odistances = geometryZoom.getDistances();
|
List<Double> odistances = geometryZoom.getDistances();
|
||||||
|
|
||||||
|
@ -171,29 +171,24 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
if (simplification.getQuick(i) == 0 && !styleMap.containsKey(i)) {
|
if (simplification.getQuick(i) == 0 && !styleMap.containsKey(i)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
double lat = locationProvider.getLatitude(i);
|
|
||||||
double lon = locationProvider.getLongitude(i);
|
|
||||||
if (shouldAddLocation(simplification, leftLongitude, rightLongitude, bottomLatitude, topLatitude,
|
if (shouldAddLocation(simplification, leftLongitude, rightLongitude, bottomLatitude, topLatitude,
|
||||||
locationProvider, i)) {
|
locationProvider, i)) {
|
||||||
double dist = previous == -1 ? 0 : odistances.get(i);
|
double dist = previous == -1 ? 0 : odistances.get(i);
|
||||||
if (!previousVisible) {
|
if (!previousVisible) {
|
||||||
double prevLat = Double.NaN;
|
|
||||||
double prevLon = Double.NaN;
|
|
||||||
if (previous != -1) {
|
if (previous != -1) {
|
||||||
prevLat = locationProvider.getLatitude(previous);
|
addLocation(tb, previous, style, tx, ty, angles, distances, dist, styles);
|
||||||
prevLon = locationProvider.getLongitude(previous);
|
|
||||||
} else if (lastProjection != null) {
|
} else if (lastProjection != null) {
|
||||||
prevLat = lastProjection.getLatitude();
|
double prevLat = lastProjection.getLatitude();
|
||||||
prevLon = lastProjection.getLongitude();
|
double prevLon = lastProjection.getLongitude();
|
||||||
}
|
if (!Double.isNaN(prevLat) && !Double.isNaN(prevLon)) {
|
||||||
if (!Double.isNaN(prevLat) && !Double.isNaN(prevLon)) {
|
addLocation(tb, prevLat, prevLon, getStyle(i - 1, style), tx, ty, angles, distances, dist, styles); // first point
|
||||||
addLocation(tb, prevLat, prevLon, getStyle(i - 1, style), tx, ty, angles, distances, dist, styles); // first point
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addLocation(tb, lat, lon, style, tx, ty, angles, distances, dist, styles);
|
addLocation(tb, i, style, tx, ty, angles, distances, dist, styles);
|
||||||
previousVisible = true;
|
previousVisible = true;
|
||||||
} else if (previousVisible) {
|
} else if (previousVisible) {
|
||||||
addLocation(tb, lat, lon, style, tx, ty, angles, distances, previous == -1 ? 0 : odistances.get(i), styles);
|
addLocation(tb, i, style, tx, ty, angles, distances, previous == -1 ? 0 : odistances.get(i), styles);
|
||||||
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);
|
||||||
|
@ -214,7 +209,14 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
return leftLon <= lon && lon <= rightLon && bottomLat <= lat && lat <= topLat;
|
return leftLon <= lon && lon <= rightLon && bottomLat <= lat && lat <= topLat;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addLocation(RotatedTileBox tb, double latitude, double longitude, GeometryWayStyle<?> style,
|
protected void addLocation(RotatedTileBox tb, int locationIdx, GeometryWayStyle<?> style,
|
||||||
|
List<Float> tx, List<Float> ty, List<Double> angles, List<Double> distances,
|
||||||
|
double dist, List<GeometryWayStyle<?>> styles) {
|
||||||
|
addLocation(tb, locationProvider.getLatitude(locationIdx), locationProvider.getLongitude(locationIdx),
|
||||||
|
style, tx, ty, angles, distances, dist, styles);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addLocation(RotatedTileBox tb, double latitude, double longitude, GeometryWayStyle<?> style,
|
||||||
List<Float> tx, List<Float> ty, List<Double> angles, List<Double> distances,
|
List<Float> tx, List<Float> ty, List<Double> angles, List<Double> distances,
|
||||||
double dist, List<GeometryWayStyle<?>> styles) {
|
double dist, List<GeometryWayStyle<?>> styles) {
|
||||||
float x = tb.getPixXFromLatLon(latitude, longitude);
|
float x = tb.getPixXFromLatLon(latitude, longitude);
|
||||||
|
@ -372,7 +374,7 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class PathGeometryZoom {
|
protected static class PathGeometryZoom {
|
||||||
|
|
||||||
private static final float EPSILON_IN_DPI = 2;
|
private static final float EPSILON_IN_DPI = 2;
|
||||||
|
|
||||||
|
@ -390,12 +392,7 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
angles = new ArrayList<>(size);
|
angles = new ArrayList<>(size);
|
||||||
if (simplify) {
|
if (simplify) {
|
||||||
simplifyPoints.fill(0, size, (byte) 0);
|
simplifyPoints.fill(0, size, (byte) 0);
|
||||||
if (size > 0) {
|
simplify(tb, locationProvider, simplifyPoints);
|
||||||
simplifyPoints.set(0, (byte) 1);
|
|
||||||
}
|
|
||||||
double distInPix = (tb.getDistance(0, 0, tb.getPixWidth(), 0) / tb.getPixWidth());
|
|
||||||
double cullDistance = (distInPix * (EPSILON_IN_DPI * Math.max(1, tb.getDensity())));
|
|
||||||
cullRamerDouglasPeucker(simplifyPoints, locationProvider, 0, size - 1, cullDistance);
|
|
||||||
} else {
|
} else {
|
||||||
simplifyPoints.fill(0, size, (byte) 1);
|
simplifyPoints.fill(0, size, (byte) 1);
|
||||||
}
|
}
|
||||||
|
@ -422,6 +419,16 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void simplify(RotatedTileBox tb, GeometryWayProvider locationProvider, TByteArrayList simplifyPoints) {
|
||||||
|
int size = locationProvider.getSize();
|
||||||
|
if (size > 0) {
|
||||||
|
simplifyPoints.set(0, (byte) 1);
|
||||||
|
}
|
||||||
|
double distInPix = (tb.getDistance(0, 0, tb.getPixWidth(), 0) / tb.getPixWidth());
|
||||||
|
double cullDistance = (distInPix * (EPSILON_IN_DPI * Math.max(1, tb.getDensity())));
|
||||||
|
cullRamerDouglasPeucker(simplifyPoints, locationProvider, 0, size - 1, cullDistance);
|
||||||
|
}
|
||||||
|
|
||||||
public List<Double> getDistances() {
|
public List<Double> getDistances() {
|
||||||
return distances;
|
return distances;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,30 @@ package net.osmand.plus.views.layers.geometry;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PointF;
|
||||||
|
|
||||||
|
import net.osmand.GPXUtilities.GPXFile;
|
||||||
|
import net.osmand.Location;
|
||||||
|
import net.osmand.data.RotatedTileBox;
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.helpers.GpxUiHelper;
|
||||||
|
import net.osmand.plus.routing.RouteCalculationResult;
|
||||||
|
import net.osmand.plus.routing.RoutingHelper;
|
||||||
|
import net.osmand.plus.track.GradientScaleType;
|
||||||
|
import net.osmand.router.RouteColorize;
|
||||||
|
import net.osmand.router.RouteColorize.RouteColorizationPoint;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import androidx.annotation.ColorInt;
|
import androidx.annotation.ColorInt;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import gnu.trove.list.array.TByteArrayList;
|
||||||
|
|
||||||
import net.osmand.Location;
|
public class RouteGeometryWay extends GeometryWay<RouteGeometryWayContext, RouteGeometryWayDrawer> {
|
||||||
import net.osmand.data.RotatedTileBox;
|
|
||||||
import net.osmand.plus.routing.RouteCalculationResult;
|
|
||||||
import net.osmand.plus.routing.RoutingHelper;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class RouteGeometryWay extends GeometryWay<RouteGeometryWayContext, GeometryWayDrawer<RouteGeometryWayContext>> {
|
|
||||||
|
|
||||||
private RoutingHelper helper;
|
private RoutingHelper helper;
|
||||||
private RouteCalculationResult route;
|
private RouteCalculationResult route;
|
||||||
|
@ -23,34 +33,82 @@ public class RouteGeometryWay extends GeometryWay<RouteGeometryWayContext, Geome
|
||||||
private Integer customColor;
|
private Integer customColor;
|
||||||
private Float customWidth;
|
private Float customWidth;
|
||||||
private Integer customPointColor;
|
private Integer customPointColor;
|
||||||
|
private GradientScaleType scaleType;
|
||||||
|
|
||||||
public RouteGeometryWay(RouteGeometryWayContext context) {
|
public RouteGeometryWay(RouteGeometryWayContext context) {
|
||||||
super(context, new GeometryWayDrawer<>(context));
|
super(context, new RouteGeometryWayDrawer(context));
|
||||||
this.helper = context.getApp().getRoutingHelper();
|
this.helper = context.getApp().getRoutingHelper();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRouteStyleParams(@Nullable @ColorInt Integer color,
|
public void setRouteStyleParams(@Nullable @ColorInt Integer color,
|
||||||
@Nullable Float width,
|
@Nullable Float width,
|
||||||
@Nullable @ColorInt Integer pointColor) {
|
@Nullable @ColorInt Integer pointColor,
|
||||||
|
@Nullable GradientScaleType scaleType) {
|
||||||
this.customColor = color;
|
this.customColor = color;
|
||||||
this.customWidth = width;
|
this.customWidth = width;
|
||||||
this.customPointColor = pointColor;
|
this.customPointColor = pointColor;
|
||||||
|
this.scaleType = GradientScaleType.ALTITUDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
public void updateRoute(RotatedTileBox tb, RouteCalculationResult route, OsmandApplication app) {
|
||||||
@Override
|
if (tb.getMapDensity() == getMapDensity() && this.route == route) {
|
||||||
public GeometryWayStyle<RouteGeometryWayContext> getDefaultWayStyle() {
|
return;
|
||||||
Paint paint = getContext().getAttrs().paint;
|
}
|
||||||
int color = customColor != null ? customColor : paint.getColor();
|
|
||||||
float width = customWidth != null ? customWidth : paint.getStrokeWidth();
|
|
||||||
return new GeometrySolidWayStyle(getContext(), color, width, customPointColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateRoute(RotatedTileBox tb, RouteCalculationResult route) {
|
this.route = route;
|
||||||
if (tb.getMapDensity() != getMapDensity() || this.route != route) {
|
List<Location> locations = route != null ? route.getImmutableAllLocations() : Collections.<Location>emptyList();
|
||||||
this.route = route;
|
|
||||||
List<Location> locations = route != null ? route.getImmutableAllLocations() : Collections.<Location>emptyList();
|
if (scaleType == null || locations.size() < 2) {
|
||||||
updateWay(locations, tb);
|
updateWay(locations, tb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GPXFile gpxFile = GpxUiHelper.makeGpxFromRoute(route, app);
|
||||||
|
if (!gpxFile.hasAltitude) {
|
||||||
|
updateWay(locations, tb);
|
||||||
|
}
|
||||||
|
|
||||||
|
RouteColorize routeColorize = new RouteColorize(tb.getZoom(), gpxFile, null, scaleType.toColorizationType(), 0);
|
||||||
|
List<RouteColorizationPoint> points = routeColorize.getResult(false);
|
||||||
|
|
||||||
|
updateWay(new GradientGeometryWayProvider(routeColorize), createStyles(points), tb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Integer, GeometryWayStyle<?>> createStyles(List<RouteColorizationPoint> points) {
|
||||||
|
Map<Integer, GeometryWayStyle<?>> styleMap = new TreeMap<>();
|
||||||
|
|
||||||
|
for (int i = 1; i < points.size(); i++) {
|
||||||
|
GeometryGradientWayStyle style = getGradientWayStyle();
|
||||||
|
style.startColor = points.get(i - 1).color;
|
||||||
|
style.endColor = points.get(i).color;
|
||||||
|
styleMap.put(i, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
return styleMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addLocation(RotatedTileBox tb, int locationIdx, GeometryWayStyle<?> style, List<Float> tx, List<Float> ty, List<Double> angles, List<Double> distances, double dist, List<GeometryWayStyle<?>> styles) {
|
||||||
|
super.addLocation(tb, getLocationProvider().getLatitude(locationIdx),
|
||||||
|
getLocationProvider().getLongitude(locationIdx), style, tx, ty, angles, distances, dist, styles);
|
||||||
|
if (scaleType != null && tx.size() - 1 > 0) {
|
||||||
|
int idx = tx.size() - 1;
|
||||||
|
((GeometryGradientWayStyle) style).startXY = new PointF(tx.get(idx - 1), ty.get(idx - 1));
|
||||||
|
((GeometryGradientWayStyle) style).endXY = new PointF(tx.get(idx), ty.get(idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addLocation(RotatedTileBox tb, double latitude, double longitude, GeometryWayStyle<?> style, List<Float> tx, List<Float> ty, List<Double> angles, List<Double> distances, double dist, List<GeometryWayStyle<?>> styles) {
|
||||||
|
super.addLocation(tb, latitude, longitude, style, tx, ty, angles, distances, dist, styles);
|
||||||
|
if (scaleType != null) {
|
||||||
|
int lastIdx = tx.size() - 1;
|
||||||
|
((GeometryGradientWayStyle) style).startXY = new PointF(tx.get(lastIdx), ty.get(lastIdx));
|
||||||
|
((GeometryGradientWayStyle) style).startColor = getGradientLocationProvider().getColor(0);
|
||||||
|
((GeometryGradientWayStyle) style).endColor = getGradientLocationProvider().getColor(0);
|
||||||
|
if (lastIdx != 0) {
|
||||||
|
((GeometryGradientWayStyle) styles.get(lastIdx - 1)).endXY = new PointF(tx.get(lastIdx - 1), ty.get(lastIdx - 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,17 +119,125 @@ public class RouteGeometryWay extends GeometryWay<RouteGeometryWayContext, Geome
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public GeometryWayStyle<RouteGeometryWayContext> getDefaultWayStyle() {
|
||||||
|
Paint paint = getContext().getAttrs().paint;
|
||||||
|
int color = customColor != null ? customColor : paint.getColor();
|
||||||
|
float width = customWidth != null ? customWidth : paint.getStrokeWidth();
|
||||||
|
return scaleType == null ?
|
||||||
|
new GeometrySolidWayStyle(getContext(), color, width, customPointColor) :
|
||||||
|
new GeometryGradientWayStyle(getContext(), width);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GeometryGradientWayStyle getGradientWayStyle() {
|
||||||
|
return (GeometryGradientWayStyle) getDefaultWayStyle();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Location getNextVisiblePoint() {
|
public Location getNextVisiblePoint() {
|
||||||
return helper.getRoute().getCurrentStraightAnglePoint();
|
return helper.getRoute().getCurrentStraightAnglePoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GradientGeometryWayProvider getGradientLocationProvider() {
|
||||||
|
return (GradientGeometryWayProvider) getLocationProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PathGeometryZoom getGeometryZoom(RotatedTileBox tb, Map<Integer, PathGeometryZoom> zooms) {
|
||||||
|
if (scaleType == null) {
|
||||||
|
return super.getGeometryZoom(tb, zooms);
|
||||||
|
}
|
||||||
|
int zoom = tb.getZoom();
|
||||||
|
PathGeometryZoom zm = zooms.get(zoom);
|
||||||
|
if (zm == null) {
|
||||||
|
zm = new GradientPathGeometryZoom(getLocationProvider(), tb, true);
|
||||||
|
zooms.put(zoom, zm);
|
||||||
|
}
|
||||||
|
return zm;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class GradientGeometryWayProvider implements GeometryWayProvider {
|
||||||
|
|
||||||
|
private final RouteColorize routeColorize;
|
||||||
|
private final List<RouteColorizationPoint> locations;
|
||||||
|
|
||||||
|
public GradientGeometryWayProvider(RouteColorize routeColorize) {
|
||||||
|
this.routeColorize = routeColorize;
|
||||||
|
locations = routeColorize.getResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RouteColorizationPoint> simplify(int zoom) {
|
||||||
|
return routeColorize.simplify(zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColor(int index) {
|
||||||
|
return locations.get(index).color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getLatitude(int index) {
|
||||||
|
return locations.get(index).lat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getLongitude(int index) {
|
||||||
|
return locations.get(index).lon;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSize() {
|
||||||
|
return locations.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class GradientPathGeometryZoom extends PathGeometryZoom {
|
||||||
|
|
||||||
|
public GradientPathGeometryZoom(GeometryWayProvider locationProvider, RotatedTileBox tb, boolean simplify) {
|
||||||
|
super(locationProvider, tb, simplify);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void simplify(RotatedTileBox tb, GeometryWayProvider locationProvider, TByteArrayList simplifyPoints) {
|
||||||
|
if (locationProvider instanceof GradientGeometryWayProvider) {
|
||||||
|
GradientGeometryWayProvider provider = (GradientGeometryWayProvider) locationProvider;
|
||||||
|
List<RouteColorizationPoint> simplified = provider.simplify(tb.getZoom());
|
||||||
|
for (RouteColorizationPoint location : simplified) {
|
||||||
|
simplifyPoints.set(location.id, (byte) 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GeometryGradientWayStyle extends GeometryWayStyle<RouteGeometryWayContext> {
|
||||||
|
|
||||||
|
public int startColor;
|
||||||
|
public int endColor;
|
||||||
|
|
||||||
|
public PointF startXY;
|
||||||
|
public PointF endXY;
|
||||||
|
|
||||||
|
public GeometryGradientWayStyle(RouteGeometryWayContext context, Float width) {
|
||||||
|
super(context, 0xFFFFFFFF, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bitmap getPointBitmap() {
|
||||||
|
return getContext().getArrowBitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
return this == other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class GeometrySolidWayStyle extends GeometryWayStyle<RouteGeometryWayContext> {
|
private static class GeometrySolidWayStyle extends GeometryWayStyle<RouteGeometryWayContext> {
|
||||||
|
|
||||||
private Integer pointColor;
|
private Integer pointColor;
|
||||||
|
|
||||||
GeometrySolidWayStyle(RouteGeometryWayContext context, Integer color, Float width,
|
GeometrySolidWayStyle(RouteGeometryWayContext context, Integer color, Float width,
|
||||||
Integer pointColor) {
|
Integer pointColor) {
|
||||||
super(context, color, width);
|
super(context, color, width);
|
||||||
this.pointColor = pointColor;
|
this.pointColor = pointColor;
|
||||||
}
|
}
|
||||||
|
@ -97,4 +263,4 @@ public class RouteGeometryWay extends GeometryWay<RouteGeometryWayContext, Geome
|
||||||
return other instanceof GeometrySolidWayStyle;
|
return other instanceof GeometrySolidWayStyle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package net.osmand.plus.views.layers.geometry;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.LinearGradient;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Path;
|
||||||
|
import android.graphics.Shader;
|
||||||
|
|
||||||
|
import net.osmand.plus.views.layers.geometry.RouteGeometryWay.GeometryGradientWayStyle;
|
||||||
|
|
||||||
|
public class RouteGeometryWayDrawer extends GeometryWayDrawer<RouteGeometryWayContext> {
|
||||||
|
|
||||||
|
|
||||||
|
public RouteGeometryWayDrawer(RouteGeometryWayContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawPath(Canvas canvas, Path path, GeometryWayStyle<?> s) {
|
||||||
|
if (s instanceof GeometryGradientWayStyle) {
|
||||||
|
GeometryGradientWayStyle style = (GeometryGradientWayStyle) s;
|
||||||
|
LinearGradient gradient = new LinearGradient(style.startXY.x, style.startXY.y, style.endXY.x, style.endXY.y,
|
||||||
|
style.startColor, style.endColor, Shader.TileMode.CLAMP);
|
||||||
|
getContext().getAttrs().customColorPaint.setShader(gradient);
|
||||||
|
getContext().getAttrs().customColorPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
|
}
|
||||||
|
super.drawPath(canvas, path, s);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue