Add track direction arrows
This commit is contained in:
parent
13e959a6cd
commit
16e9c3f4af
3 changed files with 149 additions and 2 deletions
|
@ -34,7 +34,7 @@ public class DirectionArrowsCard extends BaseCard {
|
|||
titleView.setText(R.string.gpx_direction_arrows);
|
||||
|
||||
final CompoundButton compoundButton = view.findViewById(R.id.compound_button);
|
||||
compoundButton.setChecked(trackDrawInfo.isShowStartFinish());
|
||||
compoundButton.setChecked(trackDrawInfo.isShowArrows());
|
||||
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.osmand.plus.views;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
|
@ -109,6 +111,9 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
|||
|
||||
private Paint paintTextIcon;
|
||||
|
||||
private Bitmap arrowBitmap;
|
||||
private GeometryWayContext wayContext;
|
||||
|
||||
private OsmandRenderer osmandRenderer;
|
||||
|
||||
private ContextMenuLayer contextMenuLayer;
|
||||
|
@ -190,6 +195,9 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
|||
visitedColor = ContextCompat.getColor(view.getApplication(), R.color.color_ok);
|
||||
defPointColor = ContextCompat.getColor(view.getApplication(), R.color.gpx_color_point);
|
||||
grayColor = ContextCompat.getColor(view.getApplication(), R.color.color_favorite_gray);
|
||||
|
||||
wayContext = new GeometryWayContext(view.getContext(), view.getDensity());
|
||||
arrowBitmap = BitmapFactory.decodeResource(view.getApplication().getResources(), R.drawable.map_route_direction_arrow, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -220,6 +228,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
|||
drawSelectedFilesSplits(canvas, tileBox, selectedGPXFiles, settings);
|
||||
drawSelectedFilesPoints(canvas, tileBox, selectedGPXFiles);
|
||||
drawSelectedFilesStartEndPoints(canvas, tileBox, selectedGPXFiles);
|
||||
drawDirectionArrows(canvas, tileBox, selectedGPXFiles);
|
||||
}
|
||||
if (textLayer != null && isTextVisible()) {
|
||||
textLayer.putData(this, cache);
|
||||
|
@ -392,6 +401,144 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
|||
}
|
||||
}
|
||||
|
||||
private void drawDirectionArrows(Canvas canvas, RotatedTileBox tileBox, List<SelectedGpxFile> selectedGPXFiles) {
|
||||
if (!tileBox.isZoomAnimated()) {
|
||||
for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) {
|
||||
boolean showArrows = selectedGpxFile.getGpxFile().isShowArrows();
|
||||
if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) {
|
||||
showArrows = trackDrawInfo.isShowArrows();
|
||||
}
|
||||
if (showArrows) {
|
||||
int color = selectedGpxFile.getGpxFile().getColor(cachedColor);
|
||||
if (selectedGpxFile.isShowCurrentTrack()) {
|
||||
color = currentTrackColor;
|
||||
}
|
||||
if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) {
|
||||
color = trackDrawInfo.getColor();
|
||||
}
|
||||
int contrastColor = UiUtilities.getContrastColor(view.getApplication(), color, false);
|
||||
GeometryWayStyle arrowsWayStyle = new GeometryArrowsWayStyle(wayContext, contrastColor);
|
||||
for (TrkSegment segment : selectedGpxFile.getPointsToDisplay()) {
|
||||
List<Float> tx = new ArrayList<>();
|
||||
List<Float> ty = new ArrayList<>();
|
||||
List<Double> distances = new ArrayList<>();
|
||||
List<Double> angles = new ArrayList<>();
|
||||
|
||||
List<WptPt> points = segment.points;
|
||||
if (points.size() > 1) {
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
WptPt pt = points.get(i);
|
||||
addLocation(tileBox, pt, tx, ty, angles, distances);
|
||||
}
|
||||
}
|
||||
drawArrowsOverPath(tx, ty, angles, distances, canvas, tileBox, arrowsWayStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addLocation(RotatedTileBox tb, WptPt pt, List<Float> tx, List<Float> ty,
|
||||
List<Double> angles, List<Double> distances) {
|
||||
float x = tb.getPixXFromLatLon(pt.getLatitude(), pt.getLongitude());
|
||||
float y = tb.getPixYFromLatLon(pt.getLatitude(), pt.getLongitude());
|
||||
float px = x;
|
||||
float py = y;
|
||||
int previous = tx.size() - 1;
|
||||
if (previous >= 0) {
|
||||
px = tx.get(previous);
|
||||
py = ty.get(previous);
|
||||
}
|
||||
double angle = 0;
|
||||
if (px != x || py != y) {
|
||||
double angleRad = Math.atan2(y - py, x - px);
|
||||
angle = (angleRad * 180 / Math.PI) + 90f;
|
||||
}
|
||||
double distSegment = Math.sqrt((y - py) * (y - py) + (x - px) * (x - px));
|
||||
tx.add(x);
|
||||
ty.add(y);
|
||||
angles.add(angle);
|
||||
distances.add(distSegment);
|
||||
}
|
||||
|
||||
private void drawArrowsOverPath(List<Float> tx, List<Float> ty, List<Double> angles, List<Double> distances,
|
||||
Canvas canvas, RotatedTileBox tb, GeometryWayStyle wayStyle) {
|
||||
int pixHeight = tb.getPixHeight();
|
||||
int pixWidth = tb.getPixWidth();
|
||||
int left = -pixWidth / 4;
|
||||
int right = pixWidth + pixWidth / 4;
|
||||
int top = -pixHeight / 4;
|
||||
int bottom = pixHeight + pixHeight / 4;
|
||||
|
||||
double zoomCoef = tb.getZoomAnimation() > 0 ? (Math.pow(2, tb.getZoomAnimation() + tb.getZoomFloatPart())) : 1f;
|
||||
double pxStep = arrowBitmap.getHeight() * 4f * zoomCoef;
|
||||
double dist = 0;
|
||||
|
||||
List<RouteLayer.PathPoint> arrows = new ArrayList<>();
|
||||
for (int i = tx.size() - 2; i >= 0; i--) {
|
||||
float px = tx.get(i);
|
||||
float py = ty.get(i);
|
||||
float x = tx.get(i + 1);
|
||||
float y = ty.get(i + 1);
|
||||
double angle = angles.get(i + 1);
|
||||
double distSegment = distances.get(i + 1);
|
||||
if (distSegment == 0) {
|
||||
continue;
|
||||
}
|
||||
if (dist >= pxStep) {
|
||||
dist = 0;
|
||||
}
|
||||
double percent = 1 - (pxStep - dist) / distSegment;
|
||||
dist += distSegment;
|
||||
while (dist >= pxStep) {
|
||||
double pdx = (x - px) * percent;
|
||||
double pdy = (y - py) * percent;
|
||||
float iconx = (float) (px + pdx);
|
||||
float icony = (float) (py + pdy);
|
||||
if (isIn(iconx, icony, left, top, right, bottom)) {
|
||||
arrows.add(new RouteLayer.PathPoint(iconx, icony, angle, wayStyle));
|
||||
}
|
||||
dist -= pxStep;
|
||||
percent -= pxStep / distSegment;
|
||||
}
|
||||
}
|
||||
for (int i = arrows.size() - 1; i >= 0; i--) {
|
||||
RouteLayer.PathPoint a = arrows.get(i);
|
||||
a.draw(canvas, wayContext);
|
||||
}
|
||||
}
|
||||
|
||||
private static class GeometryArrowsWayStyle extends GeometryWayStyle {
|
||||
|
||||
protected Integer pointColor;
|
||||
|
||||
GeometryArrowsWayStyle(GeometryWayContext context, int pointColor) {
|
||||
super(context);
|
||||
this.pointColor = pointColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!super.equals(other)) {
|
||||
return false;
|
||||
}
|
||||
return other instanceof GeometryArrowsWayStyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap getPointBitmap() {
|
||||
return getContext().getArrowBitmap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPointColor() {
|
||||
return pointColor;
|
||||
}
|
||||
}
|
||||
|
||||
private void drawSelectedFilesStartEndPoints(Canvas canvas, RotatedTileBox tileBox, List<SelectedGpxFile> selectedGPXFiles) {
|
||||
if (tileBox.getZoom() >= START_ZOOM) {
|
||||
for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) {
|
||||
|
|
|
@ -372,7 +372,7 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
|
|||
}
|
||||
}
|
||||
|
||||
private static class PathPoint {
|
||||
static class PathPoint {
|
||||
float x;
|
||||
float y;
|
||||
double angle;
|
||||
|
|
Loading…
Reference in a new issue