Merge pull request #11458 from osmandapp/gradient_track_extra_tasks
Gradient track extra tasks
This commit is contained in:
commit
2d2a951dde
2 changed files with 74 additions and 39 deletions
|
@ -58,6 +58,7 @@ public class Renderable {
|
||||||
public static abstract class RenderableSegment {
|
public static abstract class RenderableSegment {
|
||||||
|
|
||||||
protected static final int MIN_CULLER_ZOOM = 16;
|
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<WptPt> points = null; // Original list of points
|
public List<WptPt> points = null; // Original list of points
|
||||||
protected List<WptPt> culled = new ArrayList<>(); // Reduced/resampled list of points
|
protected List<WptPt> 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 paint = null; // MUST be set by 'updateLocalPaint' before use
|
||||||
protected Paint borderPaint;
|
protected Paint borderPaint;
|
||||||
protected GradientScaleType scaleType = null;
|
protected GradientScaleType scaleType = null;
|
||||||
|
protected boolean drawBorder = false;
|
||||||
|
|
||||||
protected GpxGeometryWay geometryWay;
|
protected GpxGeometryWay geometryWay;
|
||||||
|
|
||||||
|
@ -93,12 +95,10 @@ public class Renderable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBorderPaint(@NonNull Paint paint) {
|
public void setGradientTrackParams(GradientScaleType gradientScaleType, @NonNull Paint borderPaint, boolean shouldDrawBorder) {
|
||||||
borderPaint = paint;
|
this.scaleType = gradientScaleType;
|
||||||
}
|
this.borderPaint = borderPaint;
|
||||||
|
this.drawBorder = shouldDrawBorder;
|
||||||
public void setGradientScaleType(GradientScaleType type) {
|
|
||||||
this.scaleType = type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GpxGeometryWay getGeometryWay() {
|
public GpxGeometryWay getGeometryWay() {
|
||||||
|
@ -119,8 +119,10 @@ public class Renderable {
|
||||||
updateLocalPaint(p);
|
updateLocalPaint(p);
|
||||||
canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
|
canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
|
||||||
if (scaleType != null) {
|
if (scaleType != null) {
|
||||||
drawSolid(points, borderPaint, canvas, tileBox);
|
if (drawBorder && zoom < BORDER_TYPE_ZOOM_THRESHOLD) {
|
||||||
drawGradient(points, paint, canvas, tileBox);
|
drawSolid(points, borderPaint, canvas, tileBox);
|
||||||
|
}
|
||||||
|
drawGradient(zoom, points, paint, canvas, tileBox);
|
||||||
} else {
|
} else {
|
||||||
drawSolid(getPointsForDrawing(), paint, canvas, tileBox);
|
drawSolid(getPointsForDrawing(), paint, canvas, tileBox);
|
||||||
}
|
}
|
||||||
|
@ -186,8 +188,9 @@ public class Renderable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void drawGradient(List<WptPt> pts, Paint p, Canvas canvas, RotatedTileBox tileBox) {
|
protected void drawGradient(double zoom, List<WptPt> pts, Paint p, Canvas canvas, RotatedTileBox tileBox) {
|
||||||
QuadRect tileBounds = tileBox.getLatLonBounds();
|
QuadRect tileBounds = tileBox.getLatLonBounds();
|
||||||
|
boolean drawSegmentBorder = drawBorder && zoom >= BORDER_TYPE_ZOOM_THRESHOLD;
|
||||||
Path path = new Path();
|
Path path = new Path();
|
||||||
boolean recalculateLastXY = true;
|
boolean recalculateLastXY = true;
|
||||||
WptPt lastPt = pts.get(0);
|
WptPt lastPt = pts.get(0);
|
||||||
|
@ -196,6 +199,9 @@ public class Renderable {
|
||||||
List<Integer> gradientColors = new ArrayList<>();
|
List<Integer> gradientColors = new ArrayList<>();
|
||||||
float gradientAngle = 0;
|
float gradientAngle = 0;
|
||||||
|
|
||||||
|
List<Path> paths = new ArrayList<>();
|
||||||
|
List<LinearGradient> gradients = new ArrayList<>();
|
||||||
|
|
||||||
for (int i = 1; i < pts.size(); i++) {
|
for (int i = 1; i < pts.size(); i++) {
|
||||||
WptPt pt = pts.get(i);
|
WptPt pt = pts.get(i);
|
||||||
WptPt nextPt = i + 1 < pts.size() ? pts.get(i + 1) : null;
|
WptPt nextPt = i + 1 < pts.size() ? pts.get(i + 1) : null;
|
||||||
|
@ -209,8 +215,8 @@ public class Renderable {
|
||||||
lastX = tileBox.getPixXFromLatLon(lastPt.lat, lastPt.lon);
|
lastX = tileBox.getPixXFromLatLon(lastPt.lat, lastPt.lon);
|
||||||
lastY = tileBox.getPixYFromLatLon(lastPt.lat, lastPt.lon);
|
lastY = tileBox.getPixYFromLatLon(lastPt.lat, lastPt.lon);
|
||||||
if (!path.isEmpty()) {
|
if (!path.isEmpty()) {
|
||||||
p.setShader(createGradient(gradientPoints, gradientColors));
|
paths.add(new Path(path));
|
||||||
canvas.drawPath(path, p);
|
gradients.add(createGradient(gradientPoints, gradientColors));
|
||||||
}
|
}
|
||||||
path.reset();
|
path.reset();
|
||||||
path.moveTo(lastX, lastY);
|
path.moveTo(lastX, lastY);
|
||||||
|
@ -241,8 +247,21 @@ public class Renderable {
|
||||||
lastPt = pt;
|
lastPt = pt;
|
||||||
}
|
}
|
||||||
if (!path.isEmpty()) {
|
if (!path.isEmpty()) {
|
||||||
p.setShader(createGradient(gradientPoints, gradientColors));
|
paths.add(new Path(path));
|
||||||
canvas.drawPath(path, p);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,7 @@ import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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_COLOR_ATTR;
|
||||||
import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_WIDTH_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();
|
cache.clear();
|
||||||
|
removeCachedUnselectedTracks(selectedGPXFiles);
|
||||||
if (!selectedGPXFiles.isEmpty()) {
|
if (!selectedGPXFiles.isEmpty()) {
|
||||||
drawSelectedFilesSegments(canvas, tileBox, selectedGPXFiles, settings);
|
drawSelectedFilesSegments(canvas, tileBox, selectedGPXFiles, settings);
|
||||||
canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
|
canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
|
||||||
|
@ -455,22 +457,23 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
|
|
||||||
private void drawDirectionArrows(Canvas canvas, RotatedTileBox tileBox, List<SelectedGpxFile> selectedGPXFiles) {
|
private void drawDirectionArrows(Canvas canvas, RotatedTileBox tileBox, List<SelectedGpxFile> selectedGPXFiles) {
|
||||||
if (!tileBox.isZoomAnimated()) {
|
if (!tileBox.isZoomAnimated()) {
|
||||||
|
QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds());
|
||||||
for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) {
|
for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) {
|
||||||
boolean showArrows = isShowArrowsForTrack(selectedGpxFile.getGpxFile());
|
boolean showArrows = isShowArrowsForTrack(selectedGpxFile.getGpxFile());
|
||||||
if (showArrows) {
|
if (!showArrows || !QuadRect.trivialOverlap(correctedQuadRect, GPXUtilities.calculateTrackBounds(selectedGpxFile.getPointsToDisplay()))) {
|
||||||
QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds());
|
continue;
|
||||||
String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get());
|
}
|
||||||
float trackWidth = getTrackWidth(width, defaultTrackWidth);
|
String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get());
|
||||||
int trackColor = getTrackColor(selectedGpxFile.getGpxFile(), cachedColor);
|
float trackWidth = getTrackWidth(width, defaultTrackWidth);
|
||||||
int arrowColor = UiUtilities.getContrastColor(view.getApplication(), trackColor, false);
|
int trackColor = getTrackColor(selectedGpxFile.getGpxFile(), cachedColor);
|
||||||
GradientScaleType scaleType = getGradientScaleType(selectedGpxFile.getGpxFile());
|
int arrowColor = UiUtilities.getContrastColor(view.getApplication(), trackColor, false);
|
||||||
List<TrkSegment> segments = scaleType != null ?
|
GradientScaleType scaleType = getGradientScaleType(selectedGpxFile.getGpxFile());
|
||||||
getCachedSegments(selectedGpxFile, scaleType) : selectedGpxFile.getPointsToDisplay();
|
List<TrkSegment> segments = scaleType != null ?
|
||||||
for (TrkSegment segment : segments) {
|
getCachedSegments(selectedGpxFile, scaleType) : selectedGpxFile.getPointsToDisplay();
|
||||||
if (segment.renderer instanceof Renderable.RenderableSegment) {
|
for (TrkSegment segment : segments) {
|
||||||
((Renderable.RenderableSegment) segment.renderer)
|
if (segment.renderer instanceof Renderable.RenderableSegment) {
|
||||||
.drawGeometry(canvas, tileBox, correctedQuadRect, arrowColor, trackColor, trackWidth);
|
((Renderable.RenderableSegment) segment.renderer)
|
||||||
}
|
.drawGeometry(canvas, tileBox, correctedQuadRect, arrowColor, trackColor, trackWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -690,6 +693,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
RotatedTileBox tileBox, DrawSettings settings) {
|
RotatedTileBox tileBox, DrawSettings settings) {
|
||||||
boolean visible = QuadRect.trivialOverlap(tileBox.getLatLonBounds(), GPXUtilities.calculateTrackBounds(selectedGpxFile.getPointsToDisplay()));
|
boolean visible = QuadRect.trivialOverlap(tileBox.getLatLonBounds(), GPXUtilities.calculateTrackBounds(selectedGpxFile.getPointsToDisplay()));
|
||||||
if (!selectedGpxFile.getGpxFile().hasTrkPt() || !visible) {
|
if (!selectedGpxFile.getGpxFile().hasTrkPt() || !visible) {
|
||||||
|
segmentsCache.remove(selectedGpxFile.getGpxFile().path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -719,8 +723,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.setGradientTrackParams(scaleType, borderPaint, true);
|
||||||
renderableSegment.setGradientScaleType(scaleType);
|
|
||||||
renderableSegment.drawSegment(view.getZoom(), paint, canvas, tileBox);
|
renderableSegment.drawSegment(view.getZoom(), paint, canvas, tileBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -729,13 +732,12 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
private List<TrkSegment> getCachedSegments(SelectedGpxFile selectedGpxFile, GradientScaleType scaleType) {
|
private List<TrkSegment> getCachedSegments(SelectedGpxFile selectedGpxFile, GradientScaleType scaleType) {
|
||||||
GPXFile gpxFile = selectedGpxFile.getGpxFile();
|
GPXFile gpxFile = selectedGpxFile.getGpxFile();
|
||||||
String path = gpxFile.path;
|
String path = gpxFile.path;
|
||||||
long modifiedTime = gpxFile.modifiedTime;
|
|
||||||
CachedTrack cachedTrack = segmentsCache.get(path);
|
CachedTrack cachedTrack = segmentsCache.get(path);
|
||||||
if (cachedTrack == null) {
|
if (cachedTrack == null) {
|
||||||
cachedTrack = new CachedTrack(view.getApplication(), modifiedTime);
|
cachedTrack = new CachedTrack(view.getApplication(), selectedGpxFile);
|
||||||
segmentsCache.put(path, cachedTrack);
|
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) {
|
private float getTrackWidth(String width, float defaultTrackWidth) {
|
||||||
|
@ -1051,6 +1053,19 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
return name.replace('_', ' ');
|
return name.replace('_', ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeCachedUnselectedTracks(List<SelectedGpxFile> selectedGpxFiles) {
|
||||||
|
Set<String> cachedTracksPaths = segmentsCache.keySet();
|
||||||
|
List<String> selectedTracksPaths = new ArrayList<>();
|
||||||
|
for (SelectedGpxFile gpx : selectedGpxFiles) {
|
||||||
|
selectedTracksPaths.add(gpx.getGpxFile().path);
|
||||||
|
}
|
||||||
|
for (Iterator<String> iterator = cachedTracksPaths.iterator(); iterator.hasNext();) {
|
||||||
|
if (!selectedTracksPaths.contains(iterator.next())) {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean disableSingleTap() {
|
public boolean disableSingleTap() {
|
||||||
return isInTrackAppearanceMode();
|
return isInTrackAppearanceMode();
|
||||||
|
@ -1220,20 +1235,21 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
|
|
||||||
private OsmandApplication app;
|
private OsmandApplication app;
|
||||||
|
|
||||||
private long modifiedTime;
|
private final SelectedGpxFile selectedGpxFile;
|
||||||
private final Map<String, List<TrkSegment>> cache = new HashMap<>();
|
private final Map<String, List<TrkSegment>> 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.app = app;
|
||||||
this.modifiedTime = modifiedTime;
|
this.selectedGpxFile = selectedGpxFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TrkSegment> getCachedSegments(@NonNull SelectedGpxFile selectedGpxFile, int zoom,
|
public List<TrkSegment> getCachedSegments(int zoom, @NonNull GradientScaleType scaleType,
|
||||||
@NonNull GradientScaleType scaleType,
|
|
||||||
int[] gradientPalette) {
|
int[] gradientPalette) {
|
||||||
GPXFile gpxFile = selectedGpxFile.getGpxFile();
|
GPXFile gpxFile = selectedGpxFile.getGpxFile();
|
||||||
String trackId = zoom + "_" + scaleType.toString();
|
String trackId = zoom + "_" + scaleType.toString();
|
||||||
if (modifiedTime == gpxFile.modifiedTime) {
|
if (prevModifiedTime == gpxFile.modifiedTime) {
|
||||||
List<TrkSegment> segments = cache.get(trackId);
|
List<TrkSegment> segments = cache.get(trackId);
|
||||||
if (segments == null) {
|
if (segments == null) {
|
||||||
segments = calculateGradientTrack(selectedGpxFile, zoom, scaleType, gradientPalette);
|
segments = calculateGradientTrack(selectedGpxFile, zoom, scaleType, gradientPalette);
|
||||||
|
@ -1242,7 +1258,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
return segments;
|
return segments;
|
||||||
} else {
|
} else {
|
||||||
cache.clear();
|
cache.clear();
|
||||||
modifiedTime = gpxFile.modifiedTime;
|
prevModifiedTime = gpxFile.modifiedTime;
|
||||||
List<TrkSegment> segments = calculateGradientTrack(selectedGpxFile, zoom, scaleType, gradientPalette);
|
List<TrkSegment> segments = calculateGradientTrack(selectedGpxFile, zoom, scaleType, gradientPalette);
|
||||||
cache.put(trackId, segments);
|
cache.put(trackId, segments);
|
||||||
return segments;
|
return segments;
|
||||||
|
|
Loading…
Reference in a new issue