From 15fb2b677438195f5354feec6add797ee39a921c Mon Sep 17 00:00:00 2001 From: cepprice Date: Sun, 18 Apr 2021 13:23:10 +0500 Subject: [PATCH 1/4] Add drawing track border by params --- .../src/net/osmand/plus/views/Renderable.java | 39 +++++++++++++++---- .../osmand/plus/views/layers/GPXLayer.java | 1 + 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/views/Renderable.java b/OsmAnd/src/net/osmand/plus/views/Renderable.java index dd8ba55b8a..992bc06a8f 100644 --- a/OsmAnd/src/net/osmand/plus/views/Renderable.java +++ b/OsmAnd/src/net/osmand/plus/views/Renderable.java @@ -58,6 +58,7 @@ public class Renderable { public static abstract class RenderableSegment { protected static final int MIN_CULLER_ZOOM = 16; + protected static final int BORDER_TYPE_ZOOM_THRESHOLD = MapTileLayer.DEFAULT_MAX_ZOOM + MapTileLayer.OVERZOOM_IN; public List points = null; // Original list of points protected List culled = new ArrayList<>(); // Reduced/resampled list of points @@ -70,6 +71,7 @@ public class Renderable { protected Paint paint = null; // MUST be set by 'updateLocalPaint' before use protected Paint borderPaint; protected GradientScaleType scaleType = null; + protected boolean drawBorder = false; protected GpxGeometryWay geometryWay; @@ -101,6 +103,10 @@ public class Renderable { this.scaleType = type; } + public void shouldDrawBorder(boolean drawBorder) { + this.drawBorder = drawBorder; + } + public GpxGeometryWay getGeometryWay() { return geometryWay; } @@ -119,8 +125,10 @@ public class Renderable { updateLocalPaint(p); canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY()); if (scaleType != null) { - drawSolid(points, borderPaint, canvas, tileBox); - drawGradient(points, paint, canvas, tileBox); + if (drawBorder && zoom < BORDER_TYPE_ZOOM_THRESHOLD) { + drawSolid(points, borderPaint, canvas, tileBox); + } + drawGradient(zoom, points, paint, canvas, tileBox); } else { drawSolid(getPointsForDrawing(), paint, canvas, tileBox); } @@ -186,8 +194,9 @@ public class Renderable { } } - protected void drawGradient(List pts, Paint p, Canvas canvas, RotatedTileBox tileBox) { + protected void drawGradient(double zoom, List pts, Paint p, Canvas canvas, RotatedTileBox tileBox) { QuadRect tileBounds = tileBox.getLatLonBounds(); + boolean drawSegmentBorder = drawBorder && zoom >= BORDER_TYPE_ZOOM_THRESHOLD; Path path = new Path(); boolean recalculateLastXY = true; WptPt lastPt = pts.get(0); @@ -196,6 +205,9 @@ public class Renderable { List gradientColors = new ArrayList<>(); float gradientAngle = 0; + List paths = new ArrayList<>(); + List gradients = new ArrayList<>(); + for (int i = 1; i < pts.size(); i++) { WptPt pt = pts.get(i); WptPt nextPt = i + 1 < pts.size() ? pts.get(i + 1) : null; @@ -209,8 +221,8 @@ public class Renderable { lastX = tileBox.getPixXFromLatLon(lastPt.lat, lastPt.lon); lastY = tileBox.getPixYFromLatLon(lastPt.lat, lastPt.lon); if (!path.isEmpty()) { - p.setShader(createGradient(gradientPoints, gradientColors)); - canvas.drawPath(path, p); + paths.add(new Path(path)); + gradients.add(createGradient(gradientPoints, gradientColors)); } path.reset(); path.moveTo(lastX, lastY); @@ -241,8 +253,21 @@ public class Renderable { lastPt = pt; } if (!path.isEmpty()) { - p.setShader(createGradient(gradientPoints, gradientColors)); - canvas.drawPath(path, p); + paths.add(new Path(path)); + gradients.add(createGradient(gradientPoints, gradientColors)); + } + + if (!paths.isEmpty()) { + if (drawSegmentBorder) { + canvas.drawPath(paths.get(0), borderPaint); + } + for (int i = 0; i < paths.size(); i++) { + if (drawSegmentBorder && i + 1 < paths.size()) { + canvas.drawPath(paths.get(i + 1), borderPaint); + } + p.setShader(gradients.get(i)); + canvas.drawPath(paths.get(i), p); + } } } diff --git a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java index 007e6fe700..3e040a534c 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java @@ -721,6 +721,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM Renderable.RenderableSegment renderableSegment = (Renderable.RenderableSegment) ts.renderer; renderableSegment.setBorderPaint(borderPaint); renderableSegment.setGradientScaleType(scaleType); + renderableSegment.shouldDrawBorder(true); renderableSegment.drawSegment(view.getZoom(), paint, canvas, tileBox); } } From 95a1d5c9eedf10075f6484317bdc673cdf2d75e8 Mon Sep 17 00:00:00 2001 From: cepprice Date: Sun, 18 Apr 2021 14:26:10 +0500 Subject: [PATCH 2/4] Add clearing of tracks' cache --- .../osmand/plus/views/layers/GPXLayer.java | 68 ++++++++++++------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java index 3e040a534c..7873dcbbab 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java @@ -83,6 +83,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR; import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR; @@ -276,6 +277,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } } cache.clear(); + fireUnselectedGpxFiles(selectedGPXFiles); if (!selectedGPXFiles.isEmpty()) { drawSelectedFilesSegments(canvas, tileBox, selectedGPXFiles, settings); canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY()); @@ -455,22 +457,26 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM private void drawDirectionArrows(Canvas canvas, RotatedTileBox tileBox, List selectedGPXFiles) { if (!tileBox.isZoomAnimated()) { + QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds()); for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) { boolean showArrows = isShowArrowsForTrack(selectedGpxFile.getGpxFile()); - if (showArrows) { - QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds()); - String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get()); - float trackWidth = getTrackWidth(width, defaultTrackWidth); - int trackColor = getTrackColor(selectedGpxFile.getGpxFile(), cachedColor); - int arrowColor = UiUtilities.getContrastColor(view.getApplication(), trackColor, false); - GradientScaleType scaleType = getGradientScaleType(selectedGpxFile.getGpxFile()); - List segments = scaleType != null ? - getCachedSegments(selectedGpxFile, scaleType) : selectedGpxFile.getPointsToDisplay(); - for (TrkSegment segment : segments) { - if (segment.renderer instanceof Renderable.RenderableSegment) { - ((Renderable.RenderableSegment) segment.renderer) - .drawGeometry(canvas, tileBox, correctedQuadRect, arrowColor, trackColor, trackWidth); - } + if (!showArrows) { + continue; + } + if (!QuadRect.trivialOverlap(correctedQuadRect, GPXUtilities.calculateTrackBounds(selectedGpxFile.getPointsToDisplay()))) { + continue; + } + String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get()); + float trackWidth = getTrackWidth(width, defaultTrackWidth); + int trackColor = getTrackColor(selectedGpxFile.getGpxFile(), cachedColor); + int arrowColor = UiUtilities.getContrastColor(view.getApplication(), trackColor, false); + GradientScaleType scaleType = getGradientScaleType(selectedGpxFile.getGpxFile()); + List segments = scaleType != null ? + getCachedSegments(selectedGpxFile, scaleType) : selectedGpxFile.getPointsToDisplay(); + for (TrkSegment segment : segments) { + if (segment.renderer instanceof Renderable.RenderableSegment) { + ((Renderable.RenderableSegment) segment.renderer) + .drawGeometry(canvas, tileBox, correctedQuadRect, arrowColor, trackColor, trackWidth); } } } @@ -690,6 +696,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM RotatedTileBox tileBox, DrawSettings settings) { boolean visible = QuadRect.trivialOverlap(tileBox.getLatLonBounds(), GPXUtilities.calculateTrackBounds(selectedGpxFile.getPointsToDisplay())); if (!selectedGpxFile.getGpxFile().hasTrkPt() || !visible) { + segmentsCache.remove(selectedGpxFile.getGpxFile().path); return; } @@ -730,13 +737,12 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM private List getCachedSegments(SelectedGpxFile selectedGpxFile, GradientScaleType scaleType) { GPXFile gpxFile = selectedGpxFile.getGpxFile(); String path = gpxFile.path; - long modifiedTime = gpxFile.modifiedTime; CachedTrack cachedTrack = segmentsCache.get(path); if (cachedTrack == null) { - cachedTrack = new CachedTrack(view.getApplication(), modifiedTime); + cachedTrack = new CachedTrack(view.getApplication(), selectedGpxFile); segmentsCache.put(path, cachedTrack); } - return cachedTrack.getCachedSegments(selectedGpxFile, view.getZoom(), scaleType, getColorizationPalette(gpxFile, scaleType)); + return cachedTrack.getCachedSegments(view.getZoom(), scaleType, getColorizationPalette(gpxFile, scaleType)); } private float getTrackWidth(String width, float defaultTrackWidth) { @@ -1052,6 +1058,19 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM return name.replace('_', ' '); } + private void fireUnselectedGpxFiles(List selectedGpxFiles) { + Set cachedTracksPaths = segmentsCache.keySet(); + List selectedTracksPaths = new ArrayList<>(); + for (SelectedGpxFile gpx : selectedGpxFiles) { + selectedTracksPaths.add(gpx.getGpxFile().path); + } + for (String cachedPath : cachedTracksPaths) { + if (!selectedTracksPaths.contains(cachedPath)) { + cachedTracksPaths.remove(cachedPath); + } + } + } + @Override public boolean disableSingleTap() { return isInTrackAppearanceMode(); @@ -1221,20 +1240,21 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM private OsmandApplication app; - private long modifiedTime; + private final SelectedGpxFile selectedGpxFile; private final Map> cache = new HashMap<>(); - public CachedTrack(@NonNull OsmandApplication app, long modifiedTime) { + private long prevModifiedTime = -1; + + public CachedTrack(@NonNull OsmandApplication app, @NonNull SelectedGpxFile selectedGpxFile) { this.app = app; - this.modifiedTime = modifiedTime; + this.selectedGpxFile = selectedGpxFile; } - public List getCachedSegments(@NonNull SelectedGpxFile selectedGpxFile, int zoom, - @NonNull GradientScaleType scaleType, + public List getCachedSegments(int zoom, @NonNull GradientScaleType scaleType, int[] gradientPalette) { GPXFile gpxFile = selectedGpxFile.getGpxFile(); String trackId = zoom + "_" + scaleType.toString(); - if (modifiedTime == gpxFile.modifiedTime) { + if (prevModifiedTime == gpxFile.modifiedTime) { List segments = cache.get(trackId); if (segments == null) { segments = calculateGradientTrack(selectedGpxFile, zoom, scaleType, gradientPalette); @@ -1243,7 +1263,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM return segments; } else { cache.clear(); - modifiedTime = gpxFile.modifiedTime; + prevModifiedTime = gpxFile.modifiedTime; List segments = calculateGradientTrack(selectedGpxFile, zoom, scaleType, gradientPalette); cache.put(trackId, segments); return segments; From f5974f7cf3213c1f094d4c68677f569348a97bf6 Mon Sep 17 00:00:00 2001 From: cepprice Date: Sun, 18 Apr 2021 14:33:42 +0500 Subject: [PATCH 3/4] Small refactoring --- OsmAnd/src/net/osmand/plus/views/Renderable.java | 14 ++++---------- .../src/net/osmand/plus/views/layers/GPXLayer.java | 4 +--- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/views/Renderable.java b/OsmAnd/src/net/osmand/plus/views/Renderable.java index 992bc06a8f..2dbf1eb3aa 100644 --- a/OsmAnd/src/net/osmand/plus/views/Renderable.java +++ b/OsmAnd/src/net/osmand/plus/views/Renderable.java @@ -95,16 +95,10 @@ public class Renderable { } } - public void setBorderPaint(@NonNull Paint paint) { - borderPaint = paint; - } - - public void setGradientScaleType(GradientScaleType type) { - this.scaleType = type; - } - - public void shouldDrawBorder(boolean drawBorder) { - this.drawBorder = drawBorder; + public void setGradientTrackParams(GradientScaleType gradientScaleType, @NonNull Paint borderPaint, boolean shouldDrawBorder) { + this.scaleType = gradientScaleType; + this.borderPaint = borderPaint; + this.drawBorder = shouldDrawBorder; } public GpxGeometryWay getGeometryWay() { diff --git a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java index 7873dcbbab..7185fbc7c7 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java @@ -726,9 +726,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.shouldDrawBorder(true); + renderableSegment.setGradientTrackParams(scaleType, borderPaint, true); renderableSegment.drawSegment(view.getZoom(), paint, canvas, tileBox); } } From 2524a3f73a604f52bf04d607df9ff75ed60d896e Mon Sep 17 00:00:00 2001 From: cepprice Date: Sun, 18 Apr 2021 16:00:54 +0500 Subject: [PATCH 4/4] Review fixes --- .../net/osmand/plus/views/layers/GPXLayer.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java index 7185fbc7c7..7ce7ec3feb 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java @@ -277,7 +277,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } } cache.clear(); - fireUnselectedGpxFiles(selectedGPXFiles); + removeCachedUnselectedTracks(selectedGPXFiles); if (!selectedGPXFiles.isEmpty()) { drawSelectedFilesSegments(canvas, tileBox, selectedGPXFiles, settings); canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY()); @@ -460,10 +460,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds()); for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) { boolean showArrows = isShowArrowsForTrack(selectedGpxFile.getGpxFile()); - if (!showArrows) { - continue; - } - if (!QuadRect.trivialOverlap(correctedQuadRect, GPXUtilities.calculateTrackBounds(selectedGpxFile.getPointsToDisplay()))) { + if (!showArrows || !QuadRect.trivialOverlap(correctedQuadRect, GPXUtilities.calculateTrackBounds(selectedGpxFile.getPointsToDisplay()))) { continue; } String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get()); @@ -1056,15 +1053,15 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM return name.replace('_', ' '); } - private void fireUnselectedGpxFiles(List selectedGpxFiles) { + private void removeCachedUnselectedTracks(List selectedGpxFiles) { Set cachedTracksPaths = segmentsCache.keySet(); List selectedTracksPaths = new ArrayList<>(); for (SelectedGpxFile gpx : selectedGpxFiles) { selectedTracksPaths.add(gpx.getGpxFile().path); } - for (String cachedPath : cachedTracksPaths) { - if (!selectedTracksPaths.contains(cachedPath)) { - cachedTracksPaths.remove(cachedPath); + for (Iterator iterator = cachedTracksPaths.iterator(); iterator.hasNext();) { + if (!selectedTracksPaths.contains(iterator.next())) { + iterator.remove(); } } }