package net.osmand.plus.views; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.PointF; import android.graphics.RectF; import net.osmand.Location; import net.osmand.PlatformUtil; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.data.RotatedTileBox; import net.osmand.plus.ApplicationMode; import net.osmand.plus.OsmAndLocationProvider; import net.osmand.plus.R; import net.osmand.plus.base.MapViewTrackingUtilities; import org.apache.commons.logging.Log; import java.util.List; public class PointLocationLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider { private static final Log LOG = PlatformUtil.getLog(PointLocationLayer.class); protected final static int RADIUS = 7; private Paint locationPaint; private Paint area; private Paint aroundArea; private OsmandMapTileView view; private ApplicationMode appMode; private Bitmap bearingIcon; private Bitmap headingIcon; private Bitmap locationIcon; private OsmAndLocationProvider locationProvider; private MapViewTrackingUtilities mapViewTrackingUtilities; private boolean nm; public PointLocationLayer(MapViewTrackingUtilities mv) { this.mapViewTrackingUtilities = mv; } private void initUI() { locationPaint = new Paint(); locationPaint.setAntiAlias(true); locationPaint.setFilterBitmap(true); locationPaint.setDither(true); area = new Paint(); area.setColor(view.getResources().getColor(R.color.pos_area)); aroundArea = new Paint(); aroundArea.setColor(view.getResources().getColor(R.color.pos_around)); aroundArea.setStyle(Style.STROKE); aroundArea.setStrokeWidth(1); aroundArea.setAntiAlias(true); updateIcons(view.getSettings().getApplicationMode(), false); locationProvider = view.getApplication().getLocationProvider(); } @Override public void initLayer(OsmandMapTileView view) { this.view = view; initUI(); } private RectF getHeadingRect(int locationX, int locationY){ int rad = (int) (view.getDensity() * 60); return new RectF(locationX - rad, locationY - rad, locationX + rad, locationY + rad); } @Override public void onDraw(Canvas canvas, RotatedTileBox box, DrawSettings nightMode) { if(box.getZoom() < 3) { return; } // draw boolean nm = nightMode != null && nightMode.isNightMode(); updateIcons(view.getSettings().getApplicationMode(), nm); Location lastKnownLocation = locationProvider.getLastKnownLocation(); if(lastKnownLocation == null || view == null){ return; } int locationX; int locationY; if (mapViewTrackingUtilities.isMapLinkedToLocation() && !MapViewTrackingUtilities.isSmallSpeedForAnimation(lastKnownLocation) && !mapViewTrackingUtilities.isMovingToMyLocation()) { locationX = box.getPixXFromLonNoRot(box.getLongitude()); locationY = box.getPixYFromLatNoRot(box.getLatitude()); } else { locationX = box.getPixXFromLonNoRot(lastKnownLocation.getLongitude()); locationY = box.getPixYFromLatNoRot(lastKnownLocation.getLatitude()); } final double dist = box.getDistance(0, box.getPixHeight() / 2, box.getPixWidth(), box.getPixHeight() / 2); int radius = (int) (((double) box.getPixWidth()) / dist * lastKnownLocation.getAccuracy()); if (radius > RADIUS * box.getDensity()) { int allowedRad = Math.min(box.getPixWidth() / 2, box.getPixHeight() / 2); canvas.drawCircle(locationX, locationY, Math.min(radius, allowedRad), area); canvas.drawCircle(locationX, locationY, Math.min(radius, allowedRad), aroundArea); } // draw bearing/direction/location if (isLocationVisible(box, lastKnownLocation)) { boolean isBearing = lastKnownLocation.hasBearing(); Float heading = locationProvider.getHeading(); if (heading != null && mapViewTrackingUtilities.isShowViewAngle()) { canvas.save(); canvas.rotate(heading - 180, locationX, locationY); canvas.drawBitmap(headingIcon, locationX - headingIcon.getWidth() / 2, locationY - headingIcon.getHeight() / 2, locationPaint); canvas.restore(); } if (isBearing) { float bearing = lastKnownLocation.getBearing(); canvas.rotate(bearing - 90, locationX, locationY); canvas.drawBitmap(bearingIcon, locationX - bearingIcon.getWidth() / 2, locationY - bearingIcon.getHeight() / 2, locationPaint); } else { canvas.drawBitmap(locationIcon, locationX - locationIcon.getWidth() / 2, locationY - locationIcon.getHeight() / 2, locationPaint); } } } public boolean isLocationVisible(RotatedTileBox tb, Location l) { return l != null && tb.containsLatLon(l.getLatitude(), l.getLongitude()); } @Override public void destroyLayer() { } public void updateIcons(ApplicationMode appMode, boolean nighMode) { if (appMode != this.appMode || this.nm != nighMode) { this.appMode = appMode; this.nm = nighMode; final int resourceBearingDay = appMode.getResourceBearingDay(); final int resourceBearingNight = appMode.getResourceBearingNight(); final int resourceBearing = nighMode ? resourceBearingNight : resourceBearingDay; bearingIcon = BitmapFactory.decodeResource(view.getResources(), resourceBearing); final int resourceHeadingDay = appMode.getResourceHeadingDay(); final int resourceHeadingNight = appMode.getResourceHeadingNight(); final int resourceHeading = nighMode ? resourceHeadingNight : resourceHeadingDay; headingIcon = BitmapFactory.decodeResource(view.getResources(), resourceHeading); final int resourceLocationDay = appMode.getResourceLocationDay(); final int resourceLocationNight = appMode.getResourceLocationNight(); final int resourceLocation = nighMode ? resourceLocationNight : resourceLocationDay; locationIcon = BitmapFactory.decodeResource(view.getResources(), resourceLocation); area.setColor(view.getResources().getColor(!nm ? R.color.pos_area : R.color.pos_area_night)); } } @Override public boolean drawInScreenPixels() { return false; } @Override public void collectObjectsFromPoint(PointF point, RotatedTileBox tileBox, List<Object> o) { if (tileBox.getZoom() >= 3) { getMyLocationFromPoint(tileBox, point, o); } } @Override public LatLon getObjectLocation(Object o) { return getMyLocation(); } @Override public PointDescription getObjectName(Object o) { return new PointDescription(PointDescription.POINT_TYPE_MY_LOCATION, view.getContext().getString(R.string.shared_string_my_location), ""); } @Override public boolean disableSingleTap() { return false; } @Override public boolean disableLongPressOnMap() { return false; } @Override public boolean isObjectClickable(Object o) { return false; } private LatLon getMyLocation() { Location location = locationProvider.getLastKnownLocation(); if (location != null) { return new LatLon(location.getLatitude(), location.getLongitude()); } else { return null; } } private void getMyLocationFromPoint(RotatedTileBox tb, PointF point, List<? super LatLon> myLocation) { LatLon location = getMyLocation(); if (location != null && view != null) { int ex = (int) point.x; int ey = (int) point.y; int x = (int) tb.getPixXFromLatLon(location.getLatitude(), location.getLongitude()); int y = (int) tb.getPixYFromLatLon(location.getLatitude(), location.getLongitude()); int rad = (int) (18 * tb.getDensity()); if (Math.abs(x - ex) <= rad && (ey - y) <= rad && (y - ey) <= 2.5 * rad) { myLocation.add(location); } } } }