From ff7aa932a3385c4b444960188c95bc4376a6bee1 Mon Sep 17 00:00:00 2001 From: cepprice Date: Thu, 15 Apr 2021 14:10:41 +0500 Subject: [PATCH 1/7] Add gradient route line --- .../java/net/osmand/router/RouteColorize.java | 4 +- .../osmand/plus/views/layers/RouteLayer.java | 21 +- .../views/layers/geometry/GeometryWay.java | 53 +++-- .../layers/geometry/RouteGeometryWay.java | 216 ++++++++++++++++-- .../geometry/RouteGeometryWayDrawer.java | 29 +++ 5 files changed, 269 insertions(+), 54 deletions(-) create mode 100644 OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteColorize.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteColorize.java index 6a0c5c5794..62186a8bb3 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteColorize.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteColorize.java @@ -186,7 +186,7 @@ public class RouteColorize { public List getResult(boolean simplify) { List result = new ArrayList<>(); if (simplify) { - result = simplify(); + result = simplify(zoom); } else { for (int i = 0; i < latitudes.length; 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); } - private List simplify() { + public List simplify(int zoom) { if (dataList == null) { dataList = new ArrayList<>(); for (int i = 0; i < latitudes.length; i++) { diff --git a/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java index 01e6765000..f2f1ba24b5 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java @@ -4,6 +4,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Paint.Cap; @@ -11,6 +12,7 @@ import android.graphics.Path; import android.graphics.PointF; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffColorFilter; +import android.graphics.Shader; import android.graphics.drawable.Drawable; 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.TransportRoutingHelper; import net.osmand.plus.settings.backend.CommonPreference; +import net.osmand.plus.track.GradientScaleType; import net.osmand.plus.views.OsmandMapLayer; import net.osmand.plus.views.OsmandMapTileView; 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.RenderingRuleSearchRequest; import net.osmand.render.RenderingRulesStorage; +import net.osmand.router.RouteColorize; import net.osmand.router.TransportRouteResult; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; @@ -109,6 +113,7 @@ public class RouteLayer extends OsmandMapLayer implements IContextMenuProvider { private int routeLineColor; private Integer directionArrowsColor; + private GradientScaleType gradientScaleType = null; public RouteLayer(RoutingHelper helper) { this.helper = helper; @@ -331,14 +336,22 @@ public class RouteLayer extends OsmandMapLayer implements IContextMenuProvider { DrawSettings settings, RouteLineDrawInfo drawInfo) { updateAttrs(settings, tileBox); - updateRouteColors(nightMode); - paintRouteLinePreview.setColor(getRouteLineColor()); paintRouteLinePreview.setStrokeWidth(getRouteLineWidth(tileBox)); int centerX = drawInfo.getCenterX(); int centerY = drawInfo.getCenterY(); 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); if (previewIcon == null) { @@ -524,9 +537,9 @@ public class RouteLayer extends OsmandMapLayer implements IContextMenuProvider { boolean directTo = route.getRouteService() == RouteService.DIRECT_TO; boolean straight = route.getRouteService() == RouteService.STRAIGHT; publicTransportRouteGeometry.clearRoute(); - routeGeometry.updateRoute(tb, route); + routeGeometry.setRouteStyleParams(getRouteLineColor(), getRouteLineWidth(tb), getDirectionArrowsColor(), gradientScaleType); + routeGeometry.updateRoute(tb, route, view.getApplication()); updateRouteColors(nightMode); - routeGeometry.setRouteStyleParams(getRouteLineColor(), getRouteLineWidth(tb), getDirectionArrowsColor()); if (directTo) { routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude, null, 0); diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java index aed7a2f315..7e9a511286 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java @@ -126,7 +126,7 @@ public abstract class GeometryWay zooms) { int zoom = tb.getZoom(); PathGeometryZoom zm = zooms.size() > zoom ? zooms.get(zoom) : null; if (zm == null) { @@ -148,7 +148,7 @@ public abstract class GeometryWay odistances = geometryZoom.getDistances(); @@ -171,29 +171,24 @@ public abstract class GeometryWay style, + protected void addLocation(RotatedTileBox tb, int locationIdx, GeometryWayStyle style, + List tx, List ty, List angles, List distances, + double dist, List> 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 tx, List ty, List angles, List distances, double dist, List> styles) { float x = tb.getPixXFromLatLon(latitude, longitude); @@ -372,7 +374,7 @@ public abstract class GeometryWay(size); if (simplify) { simplifyPoints.fill(0, size, (byte) 0); - 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); + simplify(tb, locationProvider, simplifyPoints); } else { simplifyPoints.fill(0, size, (byte) 1); } @@ -422,6 +419,16 @@ public abstract class GeometryWay 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 getDistances() { return distances; } diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java index d46ca8cd68..bbac19c8fe 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java @@ -2,20 +2,30 @@ package net.osmand.plus.views.layers.geometry; import android.graphics.Bitmap; 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.NonNull; import androidx.annotation.Nullable; +import gnu.trove.list.array.TByteArrayList; -import net.osmand.Location; -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> { +public class RouteGeometryWay extends GeometryWay { private RoutingHelper helper; private RouteCalculationResult route; @@ -23,34 +33,82 @@ public class RouteGeometryWay extends GeometryWay(context)); + super(context, new RouteGeometryWayDrawer(context)); this.helper = context.getApp().getRoutingHelper(); } public void setRouteStyleParams(@Nullable @ColorInt Integer color, @Nullable Float width, - @Nullable @ColorInt Integer pointColor) { + @Nullable @ColorInt Integer pointColor, + @Nullable GradientScaleType scaleType) { this.customColor = color; this.customWidth = width; this.customPointColor = pointColor; + this.scaleType = GradientScaleType.ALTITUDE; } - @NonNull - @Override - public GeometryWayStyle getDefaultWayStyle() { - 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, OsmandApplication app) { + if (tb.getMapDensity() == getMapDensity() && this.route == route) { + return; + } - public void updateRoute(RotatedTileBox tb, RouteCalculationResult route) { - if (tb.getMapDensity() != getMapDensity() || this.route != route) { - this.route = route; - List locations = route != null ? route.getImmutableAllLocations() : Collections.emptyList(); + this.route = route; + List locations = route != null ? route.getImmutableAllLocations() : Collections.emptyList(); + + if (scaleType == null || locations.size() < 2) { 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 points = routeColorize.getResult(false); + + updateWay(new GradientGeometryWayProvider(routeColorize), createStyles(points), tb); + } + + private Map> createStyles(List points) { + Map> 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 tx, List ty, List angles, List distances, double dist, List> 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 tx, List ty, List angles, List distances, double dist, List> 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 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 public Location getNextVisiblePoint() { return helper.getRoute().getCurrentStraightAnglePoint(); } + private GradientGeometryWayProvider getGradientLocationProvider() { + return (GradientGeometryWayProvider) getLocationProvider(); + } + + @Override + protected PathGeometryZoom getGeometryZoom(RotatedTileBox tb, Map 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 locations; + + public GradientGeometryWayProvider(RouteColorize routeColorize) { + this.routeColorize = routeColorize; + locations = routeColorize.getResult(false); + } + + public List 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 simplified = provider.simplify(tb.getZoom()); + for (RouteColorizationPoint location : simplified) { + simplifyPoints.set(location.id, (byte) 1); + } + } + } + } + + public static class GeometryGradientWayStyle extends GeometryWayStyle { + + 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 { private Integer pointColor; GeometrySolidWayStyle(RouteGeometryWayContext context, Integer color, Float width, - Integer pointColor) { + Integer pointColor) { super(context, color, width); this.pointColor = pointColor; } @@ -97,4 +263,4 @@ public class RouteGeometryWay extends GeometryWay { + + + 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); + } +} \ No newline at end of file From 149b89090bc1253af7b3c802050b14d38c68a772 Mon Sep 17 00:00:00 2001 From: cepprice Date: Thu, 15 Apr 2021 17:28:48 +0500 Subject: [PATCH 2/7] Add configurable drawing of route line border --- .../osmand/plus/views/layers/RouteLayer.java | 2 ++ .../views/layers/geometry/GeometryWay.java | 19 ++++++++++-- .../layers/geometry/GeometryWayDrawer.java | 7 +++++ .../layers/geometry/RouteGeometryWay.java | 12 ++++++- .../geometry/RouteGeometryWayDrawer.java | 31 ++++++++++++++++++- 5 files changed, 67 insertions(+), 4 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java index f2f1ba24b5..e74b0242ce 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java @@ -141,6 +141,8 @@ public class RouteLayer extends OsmandMapLayer implements IContextMenuProvider { attrs.defaultWidth = (int) (12 * density); attrs.defaultWidth3 = (int) (7 * density); attrs.defaultColor = view.getResources().getColor(R.color.nav_track); + attrs.shadowPaint.setColor(0x80000000); + attrs.shadowPaint.setStrokeCap(Cap.ROUND); attrs.paint3.setStrokeCap(Cap.BUTT); attrs.paint3.setColor(Color.WHITE); attrs.paint2.setStrokeCap(Cap.BUTT); diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java index 7e9a511286..2cfb950200 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java @@ -168,7 +168,7 @@ public abstract class GeometryWay> styleMap, int locationIdx) { + return simplification.getQuick(locationIdx) == 0 && !styleMap.containsKey(locationIdx); + } + protected boolean shouldAddLocation(TByteArrayList simplification, double leftLon, double rightLon, double bottomLat, double topLat, GeometryWayProvider provider, int currLocationIdx) { double lat = provider.getLatitude(currLocationIdx); @@ -358,7 +362,18 @@ public abstract class GeometryWay>> paths = new ArrayList<>(); canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY()); calculatePath(tb, tx, ty, styles, paths); - for (Pair> pc : paths) { + + drawer.drawFullBorder(canvas, tb.getZoom(), paths); + drawer.drawSegmentBorder(canvas, tb.getZoom(), paths.get(0).first, paths.get(0).second); + for (int i = 1; i <= paths.size(); i++) { + if (i != paths.size()) { + Pair> prev = paths.get(i); + if (prev.second.hasPathLine()) { + drawer.drawSegmentBorder(canvas, tb.getZoom(), prev.first, prev.second); + } + } + + Pair> pc = paths.get(i - 1); GeometryWayStyle style = pc.second; if (style.hasPathLine()) { drawer.drawPath(canvas, pc.first, style); diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWayDrawer.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWayDrawer.java index 494375d404..2b607563e5 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWayDrawer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWayDrawer.java @@ -7,6 +7,7 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.util.Pair; import net.osmand.data.RotatedTileBox; @@ -89,6 +90,12 @@ public class GeometryWayDrawer { } } + protected void drawFullBorder(Canvas canvas, int zoom, List>> paths) { + } + + protected void drawSegmentBorder(Canvas canvas, int zoom, Path path, GeometryWayStyle style) { + } + protected PathPoint getArrowPathPoint(float iconx, float icony, GeometryWayStyle style, double angle) { return new PathPoint(iconx, icony, angle, style); } diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java index bbac19c8fe..d78653b93a 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java @@ -36,7 +36,7 @@ public class RouteGeometryWay extends GeometryWay> styleMap, int locationIdx) { + return scaleType == null ? + super.shouldSkipLocation(simplification, styleMap, locationIdx) : + simplification.getQuick(locationIdx) == 0; + } + @Override protected void addLocation(RotatedTileBox tb, int locationIdx, GeometryWayStyle style, List tx, List ty, List angles, List distances, double dist, List> styles) { super.addLocation(tb, getLocationProvider().getLatitude(locationIdx), diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java index 8c1d9a8868..060370e546 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java @@ -5,14 +5,36 @@ import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Shader; +import android.util.Pair; +import net.osmand.plus.views.MapTileLayer; import net.osmand.plus.views.layers.geometry.RouteGeometryWay.GeometryGradientWayStyle; +import java.util.List; + public class RouteGeometryWayDrawer extends GeometryWayDrawer { + private final int BORDER_TYPE_ZOOM_THRESHOLD = MapTileLayer.DEFAULT_MIN_ZOOM; - public RouteGeometryWayDrawer(RouteGeometryWayContext context) { + private final boolean drawBorder; + + public RouteGeometryWayDrawer(RouteGeometryWayContext context, boolean drawBorder) { super(context); + this.drawBorder = drawBorder; + } + + @Override + protected void drawFullBorder(Canvas canvas, int zoom, List>> paths) { + if (drawBorder && zoom > BORDER_TYPE_ZOOM_THRESHOLD) { + Paint borderPaint = getContext().getAttrs().shadowPaint; + Path fullPath = new Path(); + for (Pair> path : paths) { + if (path.second instanceof GeometryGradientWayStyle) { + fullPath.addPath(path.first); + } + } + canvas.drawPath(fullPath, borderPaint); + } } @Override @@ -26,4 +48,11 @@ public class RouteGeometryWayDrawer extends GeometryWayDrawer style) { + if (drawBorder && zoom < BORDER_TYPE_ZOOM_THRESHOLD) { + canvas.drawPath(path, getContext().getAttrs().shadowPaint); + } + } } \ No newline at end of file From aa6b04a924e56097823b3d87c4e5f6458c9df093 Mon Sep 17 00:00:00 2001 From: cepprice Date: Fri, 16 Apr 2021 11:02:27 +0500 Subject: [PATCH 3/7] Fix spoiled points --- .../src/net/osmand/plus/helpers/GpxUiHelper.java | 15 ++++++++++++++- .../views/layers/geometry/RouteGeometryWay.java | 8 ++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java index 87f9d4e579..9d6b019cc2 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java @@ -2139,16 +2139,29 @@ public class GpxUiHelper { float h = (float) l.getAltitude(); point.ele = h; if (lastHeight == HEIGHT_UNDEFINED && seg.points.size() > 0) { - for (GPXUtilities.WptPt pt : seg.points) { + for (int i = seg.points.size() - 1; i >= 0; i--) { + GPXUtilities.WptPt pt = seg.points.get(i); if (Double.isNaN(pt.ele)) { pt.ele = h; } } } lastHeight = h; + } else { + lastHeight = HEIGHT_UNDEFINED; } seg.points.add(point); } + if (lastHeight == HEIGHT_UNDEFINED && gpx.hasAltitude) { + int start = seg.points.size() - 1; + while (start > 0 && Double.isNaN(seg.points.get(start).ele)) { + start--; + } + double ele = seg.points.get(start).ele; + for (int i = start + 1; i < seg.points.size(); i++) { + seg.points.get(i).ele = ele; + } + } track.segments.add(seg); gpx.tracks.add(track); } diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java index d78653b93a..314e299760 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java @@ -4,6 +4,7 @@ import android.graphics.Bitmap; import android.graphics.Paint; import android.graphics.PointF; +import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; import net.osmand.Location; import net.osmand.data.RotatedTileBox; @@ -71,6 +72,13 @@ public class RouteGeometryWay extends GeometryWay pts = gpxFile.tracks.get(0).segments.get(0).points; + GPXUtilities.WptPt firstPt = pts.get(0); + if (firstPt.ele == 0) { + firstPt.ele = pts.get(1).ele; + } + RouteColorize routeColorize = new RouteColorize(tb.getZoom(), gpxFile, null, scaleType.toColorizationType(), 0); List points = routeColorize.getResult(false); From 0bdf2dfa8a2e15ac78fa6f74c084805619723253 Mon Sep 17 00:00:00 2001 From: cepprice Date: Fri, 16 Apr 2021 17:51:01 +0500 Subject: [PATCH 4/7] Add UI to configure route line --- OsmAnd/res/layout/gradient_card.xml | 9 ++- OsmAnd/res/values/strings.xml | 3 + .../plus/routing/RouteLineDrawInfo.java | 23 ++++++++ .../routing/cards/RouteLineColorCard.java | 57 ++++++++++++++++--- .../plus/settings/backend/OsmandSettings.java | 1 + .../fragments/ProfileAppearanceFragment.java | 5 +- .../net/osmand/plus/track/GradientCard.java | 38 ++++++++++--- .../osmand/plus/views/layers/RouteLayer.java | 23 ++++++-- .../layers/geometry/RouteGeometryWay.java | 9 ++- 9 files changed, 140 insertions(+), 28 deletions(-) diff --git a/OsmAnd/res/layout/gradient_card.xml b/OsmAnd/res/layout/gradient_card.xml index a4edba9be2..11b82f10ad 100644 --- a/OsmAnd/res/layout/gradient_card.xml +++ b/OsmAnd/res/layout/gradient_card.xml @@ -5,8 +5,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" - android:padding="@dimen/content_padding" android:paddingStart="@dimen/content_padding" + android:paddingLeft="@dimen/content_padding" + android:paddingTop="@dimen/content_padding" + android:paddingRight="@dimen/content_padding" android:paddingEnd="@dimen/content_padding"> + + \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 9959488bd2..0a6f64787d 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -12,6 +12,9 @@ --> + Max. height + Min. height + Route line will be colorized depending on the elevation profile of the route. Output User points Announce when exceeded diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteLineDrawInfo.java b/OsmAnd/src/net/osmand/plus/routing/RouteLineDrawInfo.java index 88a033edae..2bb2eec155 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteLineDrawInfo.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteLineDrawInfo.java @@ -6,12 +6,14 @@ import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import net.osmand.plus.track.GradientScaleType; import net.osmand.util.Algorithms; public class RouteLineDrawInfo { private static final String LINE_COLOR_DAY = "line_color_day"; private static final String LINE_COLOR_NIGHT = "line_color_night"; + private static final String LINE_COLOR_GRADIENT = "line_color_gradient"; private static final String LINE_WIDTH = "line_width"; private static final String NAVIGATION_ICON_ID = "navigation_icon_id"; private static final String NAVIGATION_ICON_COLOR = "navigation_icon_color"; @@ -24,6 +26,7 @@ public class RouteLineDrawInfo { @ColorInt private Integer colorDay; private Integer colorNight; + private GradientScaleType scaleType; private String width; // temporally parameters to show in preview @@ -37,9 +40,11 @@ public class RouteLineDrawInfo { public RouteLineDrawInfo(@Nullable @ColorInt Integer colorDay, @Nullable @ColorInt Integer colorNight, + @Nullable GradientScaleType gradientScaleType, @Nullable String width) { this.colorDay = colorDay; this.colorNight = colorNight; + this.scaleType = gradientScaleType; this.width = width; } @@ -50,6 +55,7 @@ public class RouteLineDrawInfo { public RouteLineDrawInfo(@NonNull RouteLineDrawInfo existed) { this.colorDay = existed.colorDay; this.colorNight = existed.colorNight; + this.scaleType = existed.scaleType; this.width = existed.width; this.iconId = existed.iconId; this.iconColor = existed.iconColor; @@ -71,6 +77,10 @@ public class RouteLineDrawInfo { this.useDefaultColor = useDefaultColor; } + public void setGradientScaleType(@Nullable GradientScaleType scaleType) { + this.scaleType = scaleType; + } + public void setWidth(@Nullable String width) { this.width = width; } @@ -108,6 +118,11 @@ public class RouteLineDrawInfo { return nightMode ? colorNight : colorDay; } + @Nullable + public GradientScaleType getGradientScaleType() { + return scaleType; + } + @Nullable public String getWidth() { return width; @@ -141,6 +156,9 @@ public class RouteLineDrawInfo { if (bundle.containsKey(LINE_COLOR_NIGHT)) { colorNight = bundle.getInt(LINE_COLOR_NIGHT); } + if (bundle.containsKey(LINE_COLOR_GRADIENT)) { + scaleType = GradientScaleType.getGradientTypeByName(bundle.getString(LINE_COLOR_GRADIENT)); + } width = bundle.getString(LINE_WIDTH); iconId = bundle.getInt(NAVIGATION_ICON_ID); iconColor = bundle.getInt(NAVIGATION_ICON_COLOR); @@ -157,6 +175,9 @@ public class RouteLineDrawInfo { if (colorNight != null) { bundle.putInt(LINE_COLOR_NIGHT, colorNight); } + if (scaleType != null) { + bundle.putString(LINE_COLOR_GRADIENT, scaleType.getTypeName()); + } if (width != null) { bundle.putString(LINE_WIDTH, width); } @@ -177,6 +198,7 @@ public class RouteLineDrawInfo { if (!Algorithms.objectEquals(getColor(false), that.getColor(false))) return false; if (!Algorithms.objectEquals(getColor(true), that.getColor(true))) return false; + if (!Algorithms.objectEquals(scaleType, that.scaleType)) return false; return Algorithms.objectEquals(width, that.width); } @@ -184,6 +206,7 @@ public class RouteLineDrawInfo { public int hashCode() { int result = colorDay != null ? colorDay.hashCode() : 0; result = 31 * result + (colorNight != null ? colorNight.hashCode() : 0); + result = 31 * result + (scaleType != null ? scaleType.getTypeName().hashCode() : 0); result = 31 * result + (width != null ? width.hashCode() : 0); return result; } diff --git a/OsmAnd/src/net/osmand/plus/routing/cards/RouteLineColorCard.java b/OsmAnd/src/net/osmand/plus/routing/cards/RouteLineColorCard.java index dc6b10f9cd..f73371d643 100644 --- a/OsmAnd/src/net/osmand/plus/routing/cards/RouteLineColorCard.java +++ b/OsmAnd/src/net/osmand/plus/routing/cards/RouteLineColorCard.java @@ -21,6 +21,7 @@ import net.osmand.AndroidUtils; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.ColorDialogs; import net.osmand.plus.helpers.enums.DayNightMode; import net.osmand.plus.routepreparationmenu.cards.BaseCard; @@ -32,6 +33,8 @@ import net.osmand.plus.settings.fragments.HeaderUiAdapter; import net.osmand.plus.track.AppearanceViewHolder; import net.osmand.plus.track.ColorsCard; import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener; +import net.osmand.plus.track.GradientCard; +import net.osmand.plus.track.GradientScaleType; import net.osmand.plus.widgets.MultiStateToggleButton; import net.osmand.plus.widgets.MultiStateToggleButton.OnRadioItemClickListener; import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem; @@ -50,6 +53,7 @@ public class RouteLineColorCard extends BaseCard implements CardListener, ColorP private HeaderUiAdapter headerUiAdapter; private ColorsCard colorsCard; + private GradientCard gradientCard; private ColorTypeAdapter colorAdapter; private RecyclerView groupRecyclerView; private TextView tvDescription; @@ -63,7 +67,9 @@ public class RouteLineColorCard extends BaseCard implements CardListener, ColorP private enum ColorMode { DEFAULT(R.string.map_widget_renderer, R.drawable.ic_action_map_style), - CUSTOM(R.string.shared_string_custom, R.drawable.ic_action_settings); + CUSTOM(R.string.shared_string_custom, R.drawable.ic_action_settings), + ALTITUDE(R.string.altitude, R.drawable.ic_action_hillshade_dark), + SLOPE(R.string.shared_string_slope, R.drawable.ic_action_altitude_ascent); ColorMode(int titleId, int iconId) { this.titleId = titleId; @@ -107,28 +113,43 @@ public class RouteLineColorCard extends BaseCard implements CardListener, ColorP setupRadioGroup(radioGroup); cardsContainer = (ViewGroup) view.findViewById(R.id.colors_card_container); - createColorSelector(cardsContainer); + createCards(cardsContainer); initSelectedMode(); } private void initSelectedMode() { - selectedMode = getRouteLineColor() == null ? ColorMode.DEFAULT : ColorMode.CUSTOM; + if (routeLineDrawInfo.getGradientScaleType() == GradientScaleType.ALTITUDE) { + selectedMode = ColorMode.ALTITUDE; + } else if (routeLineDrawInfo.getGradientScaleType() == GradientScaleType.SLOPE) { + selectedMode = ColorMode.SLOPE; + } else { + selectedMode = getRouteLineColor() == null ? ColorMode.DEFAULT : ColorMode.CUSTOM; + } modeChanged(); } private void modeChanged() { if (selectedMode == ColorMode.DEFAULT) { themeToggleContainer.setVisibility(View.GONE); - cardsContainer.setVisibility(View.GONE); + AndroidUiHelper.updateVisibility(colorsCard.getView(), false); + AndroidUiHelper.updateVisibility(gradientCard.getView(), false); routeLineDrawInfo.setUseDefaultColor(true); changeMapTheme(initMapTheme); - } else { + } else if (selectedMode == ColorMode.CUSTOM) { themeToggleContainer.setVisibility(View.VISIBLE); - cardsContainer.setVisibility(View.VISIBLE); + AndroidUiHelper.updateVisibility(colorsCard.getView(), true); + AndroidUiHelper.updateVisibility(gradientCard.getView(), false); routeLineDrawInfo.setUseDefaultColor(false); changeMapTheme(isNightMap() ? DayNightMode.NIGHT : DayNightMode.DAY); + } else { + gradientCard.setSelectedScaleType(getGradientScaleTypeFromMode()); + AndroidUiHelper.updateVisibility(colorsCard.getView(), false); + AndroidUiHelper.updateVisibility(gradientCard.getView(), true); + themeToggleContainer.setVisibility(View.GONE); + routeLineDrawInfo.setUseDefaultColor(false); } + routeLineDrawInfo.setGradientScaleType(getGradientScaleTypeFromMode()); updateColorItems(); updateDescription(); } @@ -169,7 +190,7 @@ public class RouteLineColorCard extends BaseCard implements CardListener, ColorP } } - private void createColorSelector(ViewGroup container) { + private void createCards(ViewGroup container) { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { List colors = new ArrayList<>(); @@ -183,6 +204,9 @@ public class RouteLineColorCard extends BaseCard implements CardListener, ColorP colorsCard = new ColorsCard(mapActivity, selectedColor, targetFragment, colors, preference, null); colorsCard.setListener(this); container.addView(colorsCard.build(mapActivity)); + + gradientCard = new GradientCard(mapActivity, routeLineDrawInfo.getGradientScaleType()); + container.addView(gradientCard.build(mapActivity)); } } @@ -211,6 +235,17 @@ public class RouteLineColorCard extends BaseCard implements CardListener, ColorP return routeLineDrawInfo.getColor(isNightMap()); } + @Nullable + private GradientScaleType getGradientScaleTypeFromMode() { + if (selectedMode == ColorMode.ALTITUDE) { + return GradientScaleType.ALTITUDE; + } else if (selectedMode == ColorMode.SLOPE) { + return GradientScaleType.SLOPE; + } else { + return null; + } + } + private void updateSelectedColor() { int selectedColor = colorsCard.getSelectedColor(); routeLineDrawInfo.setColor(selectedColor, isNightMap()); @@ -234,6 +269,8 @@ public class RouteLineColorCard extends BaseCard implements CardListener, ColorP String colorName = ""; if (selectedMode == ColorMode.DEFAULT) { colorName = app.getString(R.string.map_widget_renderer); + } else if (selectedMode == ColorMode.ALTITUDE || selectedMode == ColorMode.SLOPE) { + colorName = app.getString(selectedMode.titleId); } else if (getRouteLineColor() != null) { int colorNameId = ColorDialogs.getColorName(getRouteLineColor()); colorName = app.getString(colorNameId); @@ -247,10 +284,12 @@ public class RouteLineColorCard extends BaseCard implements CardListener, ColorP String pattern = app.getString(R.string.route_line_use_map_style_appearance); String color = app.getString(R.string.shared_string_color).toLowerCase(); description = String.format(pattern, color, app.getRendererRegistry().getSelectedRendererName()); - } else { + } else if (selectedMode == ColorMode.CUSTOM) { String pattern = app.getString(R.string.specify_color_for_map_mode); String mapModeTitle = app.getString(isNightMap() ? NIGHT_TITLE_ID : DAY_TITLE_ID); description = String.format(pattern, mapModeTitle.toLowerCase()); + } else { + description = app.getString(R.string.route_line_use_gradient_coloring); } tvDescription.setText(description); } @@ -367,4 +406,4 @@ public class RouteLineColorCard extends BaseCard implements CardListener, ColorP void onMapThemeUpdated(@NonNull DayNightMode mapTheme); } -} +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java index 1a77de50fb..c186146d81 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java @@ -2705,6 +2705,7 @@ public class OsmandSettings { public final ListStringPreference CUSTOM_ROUTE_LINE_COLORS = (ListStringPreference) new ListStringPreference(this, "custom_route_line_colors", null, ",").makeShared().makeGlobal(); public final CommonPreference ROUTE_LINE_COLOR_DAY = new IntPreference(this, "route_line_color", 0).cache().makeProfile(); public final CommonPreference ROUTE_LINE_COLOR_NIGHT = new IntPreference(this, "route_line_color_night", 0).cache().makeProfile(); + public final CommonPreference ROUTE_LINE_GRADIENT = new EnumStringPreference<>(this, "route_line_gradient", null, new GradientScaleType[] {GradientScaleType.ALTITUDE, GradientScaleType.SLOPE}).cache().makeProfile(); public final CommonPreference ROUTE_LINE_WIDTH = new StringPreference(this, "route_line_width", null).makeProfile(); public final OsmandPreference USE_OSM_LIVE_FOR_ROUTING = new BooleanPreference(this, "enable_osmc_routing", true).makeProfile(); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java index c8d600315c..9bae7b1088 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java @@ -63,6 +63,7 @@ import net.osmand.plus.settings.backend.backup.SettingsHelper; import net.osmand.plus.settings.fragments.RouteLineAppearanceFragment.OnApplyRouteLineListener; import net.osmand.plus.track.ColorsCard; import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener; +import net.osmand.plus.track.GradientScaleType; import net.osmand.plus.widgets.FlowLayout; import net.osmand.plus.widgets.OsmandTextFieldBoxes; import net.osmand.util.Algorithms; @@ -1021,8 +1022,9 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O private RouteLineDrawInfo createRouteLineDrawInfo(@NonNull ApplicationMode appMode) { Integer colorDay = getRouteLineColor(appMode, settings.ROUTE_LINE_COLOR_DAY); Integer colorNight = getRouteLineColor(appMode, settings.ROUTE_LINE_COLOR_NIGHT); + GradientScaleType scaleType = settings.ROUTE_LINE_GRADIENT.getModeValue(appMode); String widthKey = settings.ROUTE_LINE_WIDTH.getModeValue(appMode); - return new RouteLineDrawInfo(colorDay, colorNight, widthKey); + return new RouteLineDrawInfo(colorDay, colorNight, scaleType, widthKey); } private Integer getRouteLineColor(@NonNull ApplicationMode appMode, @@ -1035,6 +1037,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O @NonNull RouteLineDrawInfo drawInfo) { saveRouteLineColor(appMode, settings.ROUTE_LINE_COLOR_DAY, drawInfo.getColor(false)); saveRouteLineColor(appMode, settings.ROUTE_LINE_COLOR_NIGHT, drawInfo.getColor(true)); + settings.ROUTE_LINE_GRADIENT.setModeValue(appMode, drawInfo.getGradientScaleType()); settings.ROUTE_LINE_WIDTH.setModeValue(appMode, drawInfo.getWidth()); } diff --git a/OsmAnd/src/net/osmand/plus/track/GradientCard.java b/OsmAnd/src/net/osmand/plus/track/GradientCard.java index 3c34d9f68d..de2623decf 100644 --- a/OsmAnd/src/net/osmand/plus/track/GradientCard.java +++ b/OsmAnd/src/net/osmand/plus/track/GradientCard.java @@ -19,15 +19,24 @@ import androidx.annotation.Nullable; public class GradientCard extends BaseCard { - private GPXTrackAnalysis gpxTrackAnalysis; + private final GPXTrackAnalysis gpxTrackAnalysis; private GradientScaleType selectedScaleType; + private final int minSlope = 0; + private final int maxSlope = 60; + public GradientCard(@NonNull MapActivity mapActivity, @NonNull GPXTrackAnalysis gpxTrackAnalysis, @Nullable GradientScaleType selectedScaleType) { super(mapActivity); this.gpxTrackAnalysis = gpxTrackAnalysis; this.selectedScaleType = selectedScaleType; } + public GradientCard(@NonNull MapActivity mapActivity, @Nullable GradientScaleType scaleType) { + super(mapActivity); + this.gpxTrackAnalysis = null; + this.selectedScaleType = scaleType; + } + @Override public int getCardLayoutId() { return R.layout.gradient_card; @@ -40,14 +49,27 @@ public class GradientCard extends BaseCard { return; } - AndroidUiHelper.updateVisibility(view, true); TextView minValue = view.findViewById(R.id.min_value); TextView maxValue = view.findViewById(R.id.max_value); - double min = RouteColorize.getMinValue(selectedScaleType.toColorizationType(), gpxTrackAnalysis); - double max = RouteColorize.getMaxValue(selectedScaleType.toColorizationType(), - gpxTrackAnalysis, min, app.getSettings().getApplicationMode().getMaxSpeed()); - minValue.setText(formatValue(min)); - maxValue.setText(formatValue(max)); + + if (gpxTrackAnalysis != null) { + AndroidUiHelper.updateVisibility(view, true); + double min = RouteColorize.getMinValue(selectedScaleType.toColorizationType(), gpxTrackAnalysis); + double max = RouteColorize.getMaxValue(selectedScaleType.toColorizationType(), + gpxTrackAnalysis, min, app.getSettings().getApplicationMode().getMaxSpeed()); + minValue.setText(formatValue(min)); + maxValue.setText(formatValue(max)); + AndroidUiHelper.updateVisibility(view.findViewById(R.id.space), true); + } else { + if (selectedScaleType == GradientScaleType.ALTITUDE) { + minValue.setText(R.string.shared_string_min_height); + maxValue.setText(R.string.shared_string_max_height); + } else if (selectedScaleType == GradientScaleType.SLOPE) { + minValue.setText(formatValue(minSlope)); + maxValue.setText(formatValue(maxSlope)); + } + AndroidUiHelper.updateVisibility(view.findViewById(R.id.space), false); + } } public void setSelectedScaleType(GradientScaleType type) { @@ -59,7 +81,7 @@ public class GradientCard extends BaseCard { if (selectedScaleType == GradientScaleType.ALTITUDE) { return OsmAndFormatter.getFormattedAlt(value, app); } else if (selectedScaleType == GradientScaleType.SLOPE) { - return (int) value + " %"; + return app.getString(R.string.ltr_or_rtl_combine_via_space, String.valueOf((int) value), "%"); } String speed = OsmAndFormatter.getFormattedSpeed((float) value, app); String speedUnit = app.getSettings().SPEED_SYSTEM.get().toShortString(app); diff --git a/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java index e74b0242ce..9ebf2eb093 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java @@ -344,15 +344,17 @@ public class RouteLayer extends OsmandMapLayer implements IContextMenuProvider { int centerY = drawInfo.getCenterY(); int screenHeight = drawInfo.getScreenHeight(); + updateRouteColors(nightMode); + updateRouteGradient(); + + LinearGradient gradient = null; 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()); + gradient = new LinearGradient(centerX, 0, centerX, screenHeight, colors, positions, Shader.TileMode.CLAMP); } + paintRouteLinePreview.setShader(gradient); + paintRouteLinePreview.setColor(getRouteLineColor()); canvas.drawLine(centerX, 0, centerX, screenHeight, paintRouteLinePreview); @@ -475,6 +477,14 @@ public class RouteLayer extends OsmandMapLayer implements IContextMenuProvider { routeLineColor = color; } + private void updateRouteGradient() { + if (routeLineDrawInfo != null) { + gradientScaleType = routeLineDrawInfo.getGradientScaleType(); + } else { + gradientScaleType = view.getSettings().ROUTE_LINE_GRADIENT.getModeValue(helper.getAppMode()); + } + } + private float getRouteLineWidth(@NonNull RotatedTileBox tileBox) { String widthKey; if (routeLineDrawInfo != null) { @@ -539,9 +549,10 @@ public class RouteLayer extends OsmandMapLayer implements IContextMenuProvider { boolean directTo = route.getRouteService() == RouteService.DIRECT_TO; boolean straight = route.getRouteService() == RouteService.STRAIGHT; publicTransportRouteGeometry.clearRoute(); + updateRouteColors(nightMode); + updateRouteGradient(); routeGeometry.setRouteStyleParams(getRouteLineColor(), getRouteLineWidth(tb), getDirectionArrowsColor(), gradientScaleType); routeGeometry.updateRoute(tb, route, view.getApplication()); - updateRouteColors(nightMode); if (directTo) { routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude, null, 0); diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java index 314e299760..28eef91f07 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java @@ -35,6 +35,7 @@ public class RouteGeometryWay extends GeometryWay Date: Fri, 16 Apr 2021 19:23:54 +0500 Subject: [PATCH 5/7] Small fixes --- .../java/net/osmand/router/RouteColorize.java | 2 + .../views/layers/geometry/GeometryWay.java | 7 ++ .../layers/geometry/GeometryWayContext.java | 4 ++ .../layers/geometry/RouteGeometryWay.java | 66 ++++++++++--------- .../geometry/RouteGeometryWayDrawer.java | 1 - 5 files changed, 47 insertions(+), 33 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteColorize.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteColorize.java index 62186a8bb3..0db39d0695 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteColorize.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteColorize.java @@ -266,6 +266,8 @@ public class RouteColorize { List sublist = dataList.subList(prevId, currentId); simplified.addAll(getExtremums(sublist)); } + Node lastSurvivedPoint = result.get(result.size() - 1); + simplified.add(dataList.get((int) lastSurvivedPoint.getId())); return simplified; } diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java index 2cfb950200..9bb4bf9445 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java @@ -139,6 +139,11 @@ public abstract class GeometryWay getDefaultWayStyle(); + @NonNull + protected Map> getStyleMap() { + return styleMap; + } + public Location getNextVisiblePoint() { return null; } @@ -380,6 +385,8 @@ public abstract class GeometryWay style : getStyleMap().values()) { + style.width = width; + } + } this.customColor = color; this.customWidth = width; this.customPointColor = pointColor; @@ -54,50 +60,46 @@ public class RouteGeometryWay extends GeometryWay locations = route != null ? route.getImmutableAllLocations() : Collections.emptyList(); + + if (scaleType == null || locations.size() < 2) { + updateWay(locations, tb); + return; + } + GPXFile gpxFile = GpxUiHelper.makeGpxFromRoute(route, app); + if (!gpxFile.hasAltitude) { + updateWay(locations, tb); + return; + } + + // Start point can have wrong zero altitude + List pts = gpxFile.tracks.get(0).segments.get(0).points; + GPXUtilities.WptPt firstPt = pts.get(0); + if (firstPt.ele == 0) { + firstPt.ele = pts.get(1).ele; + } + + RouteColorize routeColorize = new RouteColorize(tb.getZoom(), gpxFile, null, scaleType.toColorizationType(), 0); + List points = routeColorize.getResult(false); + + updateWay(new GradientGeometryWayProvider(routeColorize, points), createStyles(points), tb); } - - this.route = route; - List locations = route != null ? route.getImmutableAllLocations() : Collections.emptyList(); - - if (scaleType == null || locations.size() < 2) { - updateWay(locations, tb); - return; - } - GPXFile gpxFile = GpxUiHelper.makeGpxFromRoute(route, app); - if (!gpxFile.hasAltitude) { - updateWay(locations, tb); - return; - } - - // Start point can have wrong zero altitude - List pts = gpxFile.tracks.get(0).segments.get(0).points; - GPXUtilities.WptPt firstPt = pts.get(0); - if (firstPt.ele == 0) { - firstPt.ele = pts.get(1).ele; - } - - RouteColorize routeColorize = new RouteColorize(tb.getZoom(), gpxFile, null, scaleType.toColorizationType(), 0); - List points = routeColorize.getResult(false); - - updateWay(new GradientGeometryWayProvider(routeColorize), createStyles(points), tb); } private Map> createStyles(List points) { Map> 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; } @@ -183,9 +185,9 @@ public class RouteGeometryWay extends GeometryWay locations; - public GradientGeometryWayProvider(RouteColorize routeColorize) { + public GradientGeometryWayProvider(RouteColorize routeColorize, List locations) { this.routeColorize = routeColorize; - locations = routeColorize.getResult(false); + this.locations = locations; } public List simplify(int zoom) { diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java index 060370e546..746283a180 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java @@ -44,7 +44,6 @@ public class RouteGeometryWayDrawer extends GeometryWayDrawer Date: Sun, 18 Apr 2021 14:43:07 +0500 Subject: [PATCH 6/7] Fix border type switching --- .../plus/views/layers/geometry/RouteGeometryWayDrawer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java index 746283a180..1f613aecd5 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWayDrawer.java @@ -14,7 +14,7 @@ import java.util.List; public class RouteGeometryWayDrawer extends GeometryWayDrawer { - private final int BORDER_TYPE_ZOOM_THRESHOLD = MapTileLayer.DEFAULT_MIN_ZOOM; + private static final int BORDER_TYPE_ZOOM_THRESHOLD = MapTileLayer.DEFAULT_MAX_ZOOM + MapTileLayer.OVERZOOM_IN; private final boolean drawBorder; @@ -25,7 +25,7 @@ public class RouteGeometryWayDrawer extends GeometryWayDrawer>> paths) { - if (drawBorder && zoom > BORDER_TYPE_ZOOM_THRESHOLD) { + if (drawBorder && zoom < BORDER_TYPE_ZOOM_THRESHOLD) { Paint borderPaint = getContext().getAttrs().shadowPaint; Path fullPath = new Path(); for (Pair> path : paths) { @@ -50,7 +50,7 @@ public class RouteGeometryWayDrawer extends GeometryWayDrawer style) { - if (drawBorder && zoom < BORDER_TYPE_ZOOM_THRESHOLD) { + if (drawBorder && zoom >= BORDER_TYPE_ZOOM_THRESHOLD) { canvas.drawPath(path, getContext().getAttrs().shadowPaint); } } From 4de1aa9193f8f646f360918f0b8dc149691af04e Mon Sep 17 00:00:00 2001 From: cepprice Date: Wed, 21 Apr 2021 23:51:15 +0500 Subject: [PATCH 7/7] Fix crash and other fixes --- .../java/net/osmand/router/RouteColorize.java | 2 +- .../net/osmand/plus/helpers/GpxUiHelper.java | 18 +++++------------- .../layers/geometry/RouteGeometryWay.java | 12 +++++------- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteColorize.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteColorize.java index 0db39d0695..ece3b01a38 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteColorize.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteColorize.java @@ -200,7 +200,7 @@ public class RouteColorize { public int getColorByValue(double value) { if (Double.isNaN(value)) { - value = (minValue + maxValue) / 2; + value = colorizationType == ColorizationType.SLOPE ? minValue : (minValue + maxValue) / 2; } for (int i = 0; i < palette.length - 1; i++) { if (value == palette[i][VALUE_INDEX]) diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java index 9d6b019cc2..75d62d6f0a 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java @@ -2124,9 +2124,12 @@ public class GpxUiHelper { public static GPXFile makeGpxFromRoute(RouteCalculationResult route, OsmandApplication app) { + return makeGpxFromLocations(route.getRouteLocations(), app); + } + + public static GPXFile makeGpxFromLocations(List locations, OsmandApplication app) { double lastHeight = HEIGHT_UNDEFINED; GPXFile gpx = new GPXUtilities.GPXFile(Version.getFullVersion(app)); - List locations = route.getRouteLocations(); if (locations != null) { GPXUtilities.Track track = new GPXUtilities.Track(); GPXUtilities.TrkSegment seg = new GPXUtilities.TrkSegment(); @@ -2139,8 +2142,7 @@ public class GpxUiHelper { float h = (float) l.getAltitude(); point.ele = h; if (lastHeight == HEIGHT_UNDEFINED && seg.points.size() > 0) { - for (int i = seg.points.size() - 1; i >= 0; i--) { - GPXUtilities.WptPt pt = seg.points.get(i); + for (GPXUtilities.WptPt pt : seg.points) { if (Double.isNaN(pt.ele)) { pt.ele = h; } @@ -2152,16 +2154,6 @@ public class GpxUiHelper { } seg.points.add(point); } - if (lastHeight == HEIGHT_UNDEFINED && gpx.hasAltitude) { - int start = seg.points.size() - 1; - while (start > 0 && Double.isNaN(seg.points.get(start).ele)) { - start--; - } - double ele = seg.points.get(start).ele; - for (int i = start + 1; i < seg.points.size(); i++) { - seg.points.get(i).ele = ele; - } - } track.segments.add(seg); gpx.tracks.add(track); } diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java index 8d3ff947e9..a21a6ad29a 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java @@ -72,7 +72,7 @@ public class RouteGeometryWay extends GeometryWay