Add border to gradient track line

This commit is contained in:
cepprice 2021-03-24 22:02:32 +05:00
parent feadaa0da5
commit faa8503847
2 changed files with 74 additions and 17 deletions

View file

@ -4,6 +4,7 @@ import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Shader;
import net.osmand.GPXUtilities;
@ -67,6 +68,7 @@ public class Renderable {
protected double zoom = -1;
protected AsynchronousResampler culler = null; // The currently active resampler
protected Paint paint = null; // MUST be set by 'updateLocalPaint' before use
protected Paint borderPaint;
protected GradientScaleType scaleType = null;
protected GpxGeometryWay geometryWay;
@ -88,6 +90,10 @@ public class Renderable {
paint.setStrokeWidth(p.getStrokeWidth());
}
public void setBorderPaint(@NonNull Paint paint) {
borderPaint = paint;
}
public void setGradientScaleType(GradientScaleType type) {
this.scaleType = type;
}
@ -177,33 +183,74 @@ public class Renderable {
protected void drawGradient(List<WptPt> pts, Paint p, Canvas canvas, RotatedTileBox tileBox) {
QuadRect tileBounds = tileBox.getLatLonBounds();
Path path = new Path();
Path currentPath = new Path();
Path nextPath = new Path();
Paint paint = new Paint(this.paint);
WptPt prevPt = pts.get(0);
WptPt prevWpt = pts.get(0);
WptPt currWpt = pts.get(1);
PointF prevXY = new PointF();
PointF currXY = new PointF();
PointF nextXY = new PointF();
boolean currLineVisible = arePointsInsideTile(prevWpt, currWpt, tileBounds);
boolean nextLineVisible;
if (currLineVisible) {
pixXYFromWptPt(tileBox, prevXY, prevWpt);
pixXYFromWptPt(tileBox, currXY, currWpt);
canvas.drawPath(pathFromStartEnd(currentPath, prevXY, currXY), borderPaint);
}
for (int i = 1; i < pts.size(); i++) {
WptPt currentPt = pts.get(i);
if (arePointsInsideTile(currentPt, prevPt, tileBounds)) {
float startX = tileBox.getPixXFromLatLon(prevPt.lat, prevPt.lon);
float startY = tileBox.getPixYFromLatLon(prevPt.lat, prevPt.lon);
float endX = tileBox.getPixXFromLatLon(currentPt.lat, currentPt.lon);
float endY = tileBox.getPixYFromLatLon(currentPt.lat, currentPt.lon);
int prevColor = prevPt.getColor(scaleType.toColorizationType());
int currentColor = currentPt.getColor(scaleType.toColorizationType());
LinearGradient gradient = new LinearGradient(startX, startY, endX, endY, prevColor, currentColor, Shader.TileMode.CLAMP);
paint.setShader(gradient);
path.reset();
path.moveTo(startX, startY);
path.lineTo(endX, endY);
canvas.drawPath(path, paint);
currWpt = pts.get(i);
WptPt nextWpt = i + 1 == pts.size() ? null : pts.get(i + 1);
nextLineVisible = arePointsInsideTile(currWpt, nextWpt, tileBounds);
if (nextWpt != null && nextLineVisible) {
pixXYFromWptPt(tileBox, currXY, currWpt);
pixXYFromWptPt(tileBox, nextXY, nextWpt);
canvas.drawPath(pathFromStartEnd(nextPath, currXY, nextXY), borderPaint);
}
prevPt = currentPt;
if (currLineVisible) {
int prevColor = prevWpt.getColor(scaleType.toColorizationType());
int currentColor = currWpt.getColor(scaleType.toColorizationType());
LinearGradient gradient = new LinearGradient(prevXY.x, prevXY.y, currXY.x, currXY.y,
prevColor, currentColor, Shader.TileMode.CLAMP);
paint.setShader(gradient);
canvas.drawPath(currentPath, paint);
}
prevWpt = currWpt;
currentPath.set(nextPath);
prevXY.set(currXY);
currXY.set(nextXY);
currLineVisible = nextLineVisible;
}
}
protected boolean arePointsInsideTile(WptPt first, WptPt second, QuadRect tileBounds) {
if (first == null || second == null) {
return false;
}
return Math.min(first.lon, second.lon) < tileBounds.right && Math.max(first.lon, second.lon) > tileBounds.left
&& Math.min(first.lat, second.lat) < tileBounds.top && Math.max(first.lat, second.lat) > tileBounds.bottom;
}
protected PointF pixXYFromWptPt(RotatedTileBox tileBox, PointF pointF, WptPt wptPt) {
pointF.x = tileBox.getPixXFromLatLon(wptPt.lat, wptPt.lon);
pointF.y = tileBox.getPixYFromLatLon(wptPt.lat, wptPt.lon);
return pointF;
}
protected Path pathFromStartEnd(Path path, PointF start, PointF end) {
path.reset();
path.moveTo(start.x, start.y);
path.lineTo(end.x, end.y);
return path;
}
}
public static class StandardTrack extends RenderableSegment {

View file

@ -95,6 +95,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
private OsmandMapTileView view;
private Paint paint;
private Paint borderPaint;
private Paint shadowPaint;
private Paint paintIcon;
@ -190,6 +191,13 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
paint = new Paint();
paint.setStyle(Style.STROKE);
paint.setAntiAlias(true);
borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
borderPaint.setStyle(Style.STROKE);
borderPaint.setStrokeJoin(Paint.Join.ROUND);
borderPaint.setStrokeCap(Paint.Cap.ROUND);
borderPaint.setColor(0x80000000);
shadowPaint = new Paint();
shadowPaint.setStyle(Style.STROKE);
shadowPaint.setAntiAlias(true);
@ -341,6 +349,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
}
paint.setColor(color == 0 ? cachedColor : color);
paint.setStrokeWidth(getTrackWidth(width, defaultTrackWidth));
borderPaint.setStrokeWidth(paint.getStrokeWidth() + AndroidUtils.dpToPx(view.getContext(), 2));
}
private void acquireTrackWidth(String widthKey, RenderingRulesStorage rrs, RenderingRuleSearchRequest req, RenderingContext rc) {
@ -700,6 +709,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
updatePaints(color, width, selectedGpxFile.isRoutePoints(), currentTrack, settings, tileBox);
if (ts.renderer instanceof Renderable.RenderableSegment) {
Renderable.RenderableSegment renderableSegment = (Renderable.RenderableSegment) ts.renderer;
renderableSegment.setBorderPaint(borderPaint);
renderableSegment.setGradientScaleType(scaleType);
renderableSegment.drawSegment(view.getZoom(), paint, canvas, tileBox);
}