package cgeo.geocaching.maps; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.interfaces.GeoPointImpl; import cgeo.geocaching.maps.interfaces.MapItemFactory; import cgeo.geocaching.maps.interfaces.MapProjectionImpl; import cgeo.geocaching.settings.Settings; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.PaintFlagsDrawFilter; import android.graphics.Point; import android.location.Location; import java.util.ArrayList; public class PositionDrawer { private Location coordinates = null; private GeoPointImpl location = null; private float heading = 0f; private Paint accuracyCircle = null; private Paint historyLine = null; private Paint historyLineShadow = null; private final Point center = new Point(); private final Point left = new Point(); private Bitmap arrow = null; private int widthArrowHalf = 0; private int heightArrowHalf = 0; private PaintFlagsDrawFilter setfil = null; private PaintFlagsDrawFilter remfil = null; private final PositionHistory positionHistory = new PositionHistory(); private final MapItemFactory mapItemFactory; public PositionDrawer() { this.mapItemFactory = Settings.getMapProvider().getMapItemFactory(); } void drawPosition(final Canvas canvas, final MapProjectionImpl projection) { if (coordinates == null || location == null) { return; } if (accuracyCircle == null) { accuracyCircle = new Paint(); accuracyCircle.setAntiAlias(true); accuracyCircle.setStrokeWidth(1.0f); } if (historyLine == null) { historyLine = new Paint(); historyLine.setAntiAlias(true); historyLine.setStrokeWidth(3.0f); historyLine.setColor(0xFFFFFFFF); } if (historyLineShadow == null) { historyLineShadow = new Paint(); historyLineShadow.setAntiAlias(true); historyLineShadow.setStrokeWidth(7.0f); historyLineShadow.setColor(0x66000000); } if (setfil == null) { setfil = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG); } if (remfil == null) { remfil = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0); } canvas.setDrawFilter(setfil); final double latitude = coordinates.getLatitude(); final double longitude = coordinates.getLongitude(); final float accuracy = coordinates.getAccuracy(); final float[] result = new float[1]; Location.distanceBetween(latitude, longitude, latitude, longitude + 1, result); final float longitudeLineDistance = result[0]; final Geopoint leftCoords = new Geopoint(latitude, longitude - accuracy / longitudeLineDistance); final GeoPointImpl leftGeo = mapItemFactory.getGeoPointBase(leftCoords); projection.toPixels(leftGeo, left); projection.toPixels(location, center); final int radius = center.x - left.x; accuracyCircle.setColor(0x66000000); accuracyCircle.setStyle(Style.STROKE); canvas.drawCircle(center.x, center.y, radius, accuracyCircle); accuracyCircle.setColor(0x08000000); accuracyCircle.setStyle(Style.FILL); canvas.drawCircle(center.x, center.y, radius, accuracyCircle); positionHistory.rememberTrailPosition(coordinates); if (Settings.isMapTrail()) { // always add current position to drawn history to have a closed connection final ArrayList<Location> paintHistory = new ArrayList<>(positionHistory.getHistory()); paintHistory.add(coordinates); final int size = paintHistory.size(); if (size > 1) { int alphaCnt = size - 201; if (alphaCnt < 1) { alphaCnt = 1; } final Point pointNow = new Point(); final Point pointPrevious = new Point(); final Location prev = paintHistory.get(0); projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(prev)), pointPrevious); for (int cnt = 1; cnt < size; cnt++) { final Location now = paintHistory.get(cnt); projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(now)), pointNow); final int alpha; if ((alphaCnt - cnt) > 0) { alpha = 255 / (alphaCnt - cnt); } else { alpha = 255; } historyLineShadow.setAlpha(alpha); historyLine.setAlpha(alpha); canvas.drawLine(pointPrevious.x, pointPrevious.y, pointNow.x, pointNow.y, historyLineShadow); canvas.drawLine(pointPrevious.x, pointPrevious.y, pointNow.x, pointNow.y, historyLine); pointPrevious.set(pointNow.x, pointNow.y); } } } if (arrow == null) { arrow = BitmapFactory.decodeResource(CgeoApplication.getInstance().getResources(), R.drawable.my_location_chevron); widthArrowHalf = arrow.getWidth() / 2; heightArrowHalf = arrow.getHeight() / 2; } final int marginLeft = center.x - widthArrowHalf; final int marginTop = center.y - heightArrowHalf; final Matrix matrix = new Matrix(); matrix.setRotate(heading, widthArrowHalf, heightArrowHalf); matrix.postTranslate(marginLeft, marginTop); canvas.drawBitmap(arrow, matrix, null); canvas.setDrawFilter(remfil); } public ArrayList<Location> getHistory() { return positionHistory.getHistory(); } public void setHistory(final ArrayList<Location> history) { positionHistory.setHistory(history); } public void setHeading(final float bearingNow) { heading = bearingNow; } public float getHeading() { return heading; } public void setCoordinates(final Location coordinatesIn) { coordinates = coordinatesIn; location = mapItemFactory.getGeoPointBase(new Geopoint(coordinates)); } public Location getCoordinates() { return coordinates; } }