Merge pull request #11247 from osmandapp/add_stroke_to_gradient_track_line

Add border to gradient track line
This commit is contained in:
Vitaliy 2021-03-29 15:27:01 +03:00 committed by GitHub
commit 3cfb56c443
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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.LinearGradient;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Shader; import android.graphics.Shader;
import net.osmand.GPXUtilities; import net.osmand.GPXUtilities;
@ -67,6 +68,7 @@ public class Renderable {
protected double zoom = -1; protected double zoom = -1;
protected AsynchronousResampler culler = null; // The currently active resampler protected AsynchronousResampler culler = null; // The currently active resampler
protected Paint paint = null; // MUST be set by 'updateLocalPaint' before use protected Paint paint = null; // MUST be set by 'updateLocalPaint' before use
protected Paint borderPaint;
protected GradientScaleType scaleType = null; protected GradientScaleType scaleType = null;
protected GpxGeometryWay geometryWay; protected GpxGeometryWay geometryWay;
@ -88,6 +90,10 @@ public class Renderable {
paint.setStrokeWidth(p.getStrokeWidth()); paint.setStrokeWidth(p.getStrokeWidth());
} }
public void setBorderPaint(@NonNull Paint paint) {
borderPaint = paint;
}
public void setGradientScaleType(GradientScaleType type) { public void setGradientScaleType(GradientScaleType type) {
this.scaleType = type; this.scaleType = type;
} }
@ -177,33 +183,74 @@ public class Renderable {
protected void drawGradient(List<WptPt> pts, Paint p, Canvas canvas, RotatedTileBox tileBox) { protected void drawGradient(List<WptPt> pts, Paint p, Canvas canvas, RotatedTileBox tileBox) {
QuadRect tileBounds = tileBox.getLatLonBounds(); QuadRect tileBounds = tileBox.getLatLonBounds();
Path path = new Path(); Path currentPath = new Path();
Path nextPath = new Path();
Paint paint = new Paint(this.paint); 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++) { for (int i = 1; i < pts.size(); i++) {
WptPt currentPt = pts.get(i); currWpt = pts.get(i);
if (arePointsInsideTile(currentPt, prevPt, tileBounds)) { WptPt nextWpt = i + 1 == pts.size() ? null : pts.get(i + 1);
float startX = tileBox.getPixXFromLatLon(prevPt.lat, prevPt.lon);
float startY = tileBox.getPixYFromLatLon(prevPt.lat, prevPt.lon); nextLineVisible = arePointsInsideTile(currWpt, nextWpt, tileBounds);
float endX = tileBox.getPixXFromLatLon(currentPt.lat, currentPt.lon); if (nextWpt != null && nextLineVisible) {
float endY = tileBox.getPixYFromLatLon(currentPt.lat, currentPt.lon); pixXYFromWptPt(tileBox, currXY, currWpt);
int prevColor = prevPt.getColor(scaleType.toColorizationType()); pixXYFromWptPt(tileBox, nextXY, nextWpt);
int currentColor = currentPt.getColor(scaleType.toColorizationType()); canvas.drawPath(pathFromStartEnd(nextPath, currXY, nextXY), borderPaint);
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);
} }
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) { 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 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; && 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 { public static class StandardTrack extends RenderableSegment {

View file

@ -95,6 +95,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
private OsmandMapTileView view; private OsmandMapTileView view;
private Paint paint; private Paint paint;
private Paint borderPaint;
private Paint shadowPaint; private Paint shadowPaint;
private Paint paintIcon; private Paint paintIcon;
@ -190,6 +191,13 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
paint = new Paint(); paint = new Paint();
paint.setStyle(Style.STROKE); paint.setStyle(Style.STROKE);
paint.setAntiAlias(true); 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 = new Paint();
shadowPaint.setStyle(Style.STROKE); shadowPaint.setStyle(Style.STROKE);
shadowPaint.setAntiAlias(true); shadowPaint.setAntiAlias(true);
@ -341,6 +349,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
} }
paint.setColor(color == 0 ? cachedColor : color); paint.setColor(color == 0 ? cachedColor : color);
paint.setStrokeWidth(getTrackWidth(width, defaultTrackWidth)); 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) { 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); updatePaints(color, width, selectedGpxFile.isRoutePoints(), currentTrack, settings, tileBox);
if (ts.renderer instanceof Renderable.RenderableSegment) { if (ts.renderer instanceof Renderable.RenderableSegment) {
Renderable.RenderableSegment renderableSegment = (Renderable.RenderableSegment) ts.renderer; Renderable.RenderableSegment renderableSegment = (Renderable.RenderableSegment) ts.renderer;
renderableSegment.setBorderPaint(borderPaint);
renderableSegment.setGradientScaleType(scaleType); renderableSegment.setGradientScaleType(scaleType);
renderableSegment.drawSegment(view.getZoom(), paint, canvas, tileBox); renderableSegment.drawSegment(view.getZoom(), paint, canvas, tileBox);
} }