Fix overlapping of border projection and minimize overlapping of gradient projection
This commit is contained in:
parent
430ff544b3
commit
5d8f6c81d1
2 changed files with 90 additions and 58 deletions
|
@ -747,7 +747,9 @@ public class MapUtils {
|
||||||
return Math.sqrt((endX - startX) * (endX - startX) + (endY - startY) * (endY - startY));
|
return Math.sqrt((endX - startX) * (endX - startX) + (endY - startY) * (endY - startY));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double getSqrtDistance(float startX, float startY, float endX, float endY) {
|
||||||
|
return Math.sqrt((endX - startX) * (endX - startX) + (endY - startY) * (endY - startY));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import net.osmand.data.RotatedTileBox;
|
||||||
import net.osmand.plus.track.GradientScaleType;
|
import net.osmand.plus.track.GradientScaleType;
|
||||||
import net.osmand.plus.views.layers.geometry.GpxGeometryWay;
|
import net.osmand.plus.views.layers.geometry.GpxGeometryWay;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
|
import net.osmand.util.MapUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -118,9 +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) {
|
||||||
drawGradient(points, p, canvas, tileBox);
|
drawSolid(points, borderPaint, canvas, tileBox);
|
||||||
|
drawGradient(points, paint, canvas, tileBox);
|
||||||
} else {
|
} else {
|
||||||
drawSolid(getPointsForDrawing(), p, canvas, tileBox);
|
drawSolid(getPointsForDrawing(), paint, canvas, tileBox);
|
||||||
}
|
}
|
||||||
canvas.rotate(tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
|
canvas.rotate(tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
|
||||||
}
|
}
|
||||||
|
@ -166,7 +168,7 @@ public class Renderable {
|
||||||
float lastX = tileBox.getPixXFromLatLon(lastPt.lat, lastPt.lon);
|
float lastX = tileBox.getPixXFromLatLon(lastPt.lat, lastPt.lon);
|
||||||
float lastY = tileBox.getPixYFromLatLon(lastPt.lat, lastPt.lon);
|
float lastY = tileBox.getPixYFromLatLon(lastPt.lat, lastPt.lon);
|
||||||
if (!path.isEmpty()) {
|
if (!path.isEmpty()) {
|
||||||
canvas.drawPath(path, paint);
|
canvas.drawPath(path, p);
|
||||||
}
|
}
|
||||||
path.reset();
|
path.reset();
|
||||||
path.moveTo(lastX, lastY);
|
path.moveTo(lastX, lastY);
|
||||||
|
@ -180,58 +182,99 @@ public class Renderable {
|
||||||
lastPt = pt;
|
lastPt = pt;
|
||||||
}
|
}
|
||||||
if (!path.isEmpty()) {
|
if (!path.isEmpty()) {
|
||||||
canvas.drawPath(path, paint);
|
canvas.drawPath(path, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 currentPath = new Path();
|
Path path = new Path();
|
||||||
Path nextPath = new Path();
|
boolean recalculateLastXY = true;
|
||||||
Paint paint = new Paint(this.paint);
|
WptPt lastPt = pts.get(0);
|
||||||
|
|
||||||
WptPt prevWpt = pts.get(0);
|
List<PointF> gradientPoints = new ArrayList<>();
|
||||||
WptPt currWpt = pts.get(1);
|
List<Integer> gradientColors = new ArrayList<>();
|
||||||
|
float gradientAngle = 0;
|
||||||
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++) {
|
||||||
currWpt = pts.get(i);
|
WptPt pt = pts.get(i);
|
||||||
WptPt nextWpt = i + 1 == pts.size() ? null : pts.get(i + 1);
|
WptPt nextPt = i + 1 < pts.size() ? pts.get(i + 1) : null;
|
||||||
|
float nextX = nextPt == null ? 0 : tileBox.getPixXFromLatLon(nextPt.lat, nextPt.lon);
|
||||||
|
float nextY = nextPt == null ? 0 : tileBox.getPixYFromLatLon(nextPt.lat, nextPt.lon);
|
||||||
|
float lastX = 0;
|
||||||
|
float lastY = 0;
|
||||||
|
if (arePointsInsideTile(pt, lastPt, tileBounds)) {
|
||||||
|
if (recalculateLastXY) {
|
||||||
|
recalculateLastXY = false;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
path.reset();
|
||||||
|
path.moveTo(lastX, lastY);
|
||||||
|
|
||||||
nextLineVisible = arePointsInsideTile(currWpt, nextWpt, tileBounds);
|
gradientPoints.clear();
|
||||||
if (nextWpt != null && nextLineVisible) {
|
gradientColors.clear();
|
||||||
pixXYFromWptPt(tileBox, currXY, currWpt);
|
gradientPoints.add(new PointF(lastX, lastY));
|
||||||
pixXYFromWptPt(tileBox, nextXY, nextWpt);
|
gradientColors.add(lastPt.getColor(scaleType.toColorizationType()));
|
||||||
canvas.drawPath(pathFromStartEnd(nextPath, currXY, nextXY), borderPaint);
|
}
|
||||||
|
float x = tileBox.getPixXFromLatLon(pt.lat, pt.lon);
|
||||||
|
float y = tileBox.getPixYFromLatLon(pt.lat, pt.lon);
|
||||||
|
path.lineTo(x, y);
|
||||||
|
gradientPoints.add(new PointF(x, y));
|
||||||
|
gradientColors.add(pt.getColor(scaleType.toColorizationType()));
|
||||||
|
|
||||||
|
if (gradientColors.size() == 2) {
|
||||||
|
gradientAngle = calculateAngle(lastX, lastY, x, y);
|
||||||
|
}
|
||||||
|
if (nextPt != null) {
|
||||||
|
float nextAngle = calculateAngle(x, y, nextX, nextY);
|
||||||
|
if (Math.abs(nextAngle - gradientAngle) > 20) {
|
||||||
|
recalculateLastXY = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
recalculateLastXY = true;
|
||||||
|
}
|
||||||
|
lastPt = pt;
|
||||||
|
}
|
||||||
|
if (!path.isEmpty()) {
|
||||||
|
p.setShader(createGradient(gradientPoints, gradientColors));
|
||||||
|
canvas.drawPath(path, p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currLineVisible) {
|
private LinearGradient createGradient(List<PointF> gradientPoints, List<Integer> gradientColors) {
|
||||||
int prevColor = prevWpt.getColor(scaleType.toColorizationType());
|
float gradientLength = 0;
|
||||||
int currentColor = currWpt.getColor(scaleType.toColorizationType());
|
List<Float> pointsLength = new ArrayList<>(gradientPoints.size() - 1);
|
||||||
LinearGradient gradient = new LinearGradient(prevXY.x, prevXY.y, currXY.x, currXY.y,
|
for (int i = 1; i < gradientPoints.size(); i++) {
|
||||||
prevColor, currentColor, Shader.TileMode.CLAMP);
|
PointF start = gradientPoints.get(i - 1);
|
||||||
paint.setShader(gradient);
|
PointF end = gradientPoints.get(i);
|
||||||
canvas.drawPath(currentPath, paint);
|
pointsLength.add((float) MapUtils.getSqrtDistance(start.x, start.y, end.x, end.y));
|
||||||
|
gradientLength += pointsLength.get(i - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
prevWpt = currWpt;
|
float[] positions = new float[gradientPoints.size()];
|
||||||
currentPath.set(nextPath);
|
positions[0] = 0;
|
||||||
prevXY.set(currXY);
|
for (int i = 1; i < gradientPoints.size(); i++) {
|
||||||
currXY.set(nextXY);
|
positions[i] = positions[i - 1] + pointsLength.get(i - 1) / gradientLength;
|
||||||
currLineVisible = nextLineVisible;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int[] colors = new int[gradientColors.size()];
|
||||||
|
for (int i = 0; i < gradientColors.size(); i++) {
|
||||||
|
colors[i] = gradientColors.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
PointF gradientStart = gradientPoints.get(0);
|
||||||
|
PointF gradientEnd = gradientPoints.get(gradientPoints.size() - 1);
|
||||||
|
return new LinearGradient(gradientStart.x, gradientStart.y, gradientEnd.x, gradientEnd.y,
|
||||||
|
colors, positions, Shader.TileMode.CLAMP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float calculateAngle(float startX, float startY, float endX, float endY) {
|
||||||
|
return (float) Math.abs(Math.toDegrees(Math.atan2(endY - startY, endX - startX)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean arePointsInsideTile(WptPt first, WptPt second, QuadRect tileBounds) {
|
protected boolean arePointsInsideTile(WptPt first, WptPt second, QuadRect tileBounds) {
|
||||||
|
@ -241,19 +284,6 @@ public class Renderable {
|
||||||
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 {
|
||||||
|
|
Loading…
Reference in a new issue