package com.robert.maps.applib.overlays;
import java.util.Locale;
import org.andnav.osm.util.GeoPoint;
import org.andnav.osm.util.TypeConverter;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.location.Location;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
import com.robert.maps.applib.R;
import com.robert.maps.applib.utils.DistanceFormatter;
import com.robert.maps.applib.utils.IconManager;
import com.robert.maps.applib.view.TileView;
import com.robert.maps.applib.view.TileView.OpenStreetMapViewProjection;
import com.robert.maps.applib.view.TileViewOverlay;
public class MyLocationOverlay extends TileViewOverlay {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
protected final Paint mPaint = new Paint();
protected Bitmap PERSON_ICON2 = null;
private Bitmap mArrow = null;
protected Bitmap TARGET_ICON = null;
private Context mCtx;
protected GeoPoint mLocation;
protected GeoPoint mTargetLocation;
private float mAccuracy;
private int mPrefAccuracy;
private float mBearing;
private float mSpeed;
private int METER_IN_PIXEL = 156412;
private Paint mPaintAccurasyFill;
private Paint mPaintAccurasyBorder;
private Paint mPaintLineToGPS;
private boolean mNeedCrosshair;
private boolean mNeedCircleDistance;
private final Paint mPaintCross = new Paint();
private final static int mCrossSize = 7;
private Location mLoc;
private DistanceFormatter mDf;
private boolean mLineToGPS;
private int mUnits;
private TextView mLabelVw;
private int mZoomLevel;
private int mScaleCorretion;
private static final int SCALE[][] = {{25000000,15000000,8000000,4000000,2000000,1000000,500000,250000,100000,50000,25000,15000,8000,4000,2000,1000,500,250,100,50,25,10,5}
,{15000,8000,4000,2000,1000,500,250,100,50,25,15,8,21120,10560,5280,3000,1500,500,250,100,50,25,10}};
private double mTouchScale;
private int mWidth;
// ===========================================================
// Constructors
// ===========================================================
public MyLocationOverlay(final Context ctx){
mCtx = ctx.getApplicationContext();
mPaintAccurasyFill = new Paint();
mPaintAccurasyFill.setAntiAlias(true);
mPaintAccurasyFill.setStrokeWidth(2);
mPaintAccurasyFill.setStyle(Paint.Style.FILL);
mPaintAccurasyFill.setColor(0x4490B8D8);
mPaintAccurasyBorder = new Paint(mPaintAccurasyFill);
mPaintAccurasyBorder.setStyle(Paint.Style.STROKE);
mPaintAccurasyBorder.setColor(0xFF90B8D8);
mPaintLineToGPS = new Paint(mPaintAccurasyFill);
mPaintLineToGPS.setColor(ctx.getResources().getColor(R.color.line_to_gps));
mPaintCross.setAntiAlias(true);
mPaintCross.setStyle(Paint.Style.STROKE);
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(ctx);
mPrefAccuracy = Integer.parseInt(pref.getString("pref_accuracy", "1").replace("\"", ""));
mNeedCrosshair = pref.getBoolean("pref_crosshair", true);
mNeedCircleDistance = pref.getBoolean("pref_circle_distance", true);
mLineToGPS = pref.getBoolean("pref_line_gps", false);
mUnits = Integer.parseInt(pref.getString("pref_units", "0"));
mDf = new DistanceFormatter(ctx);
mScaleCorretion = 0;
if(mLineToGPS) {
mLabelVw = (TextView) LayoutInflater.from(ctx).inflate(R.layout.label_map, null);
mLabelVw.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
}
// ===========================================================
// Getter & Setter
// ===========================================================
private boolean getPersonIcon(){
if(PERSON_ICON2 == null)
this.PERSON_ICON2 = IconManager.getInstance(mCtx).getLocationIcon();
return PERSON_ICON2 == null ? false : true;
}
private boolean getArrowIcon(){
if(mArrow == null)
this.mArrow = IconManager.getInstance(mCtx).getArrowIcon();
return mArrow == null ? false : true;
}
private boolean getTargetIcon(){
if(TARGET_ICON == null)
this.TARGET_ICON = IconManager.getInstance(mCtx).getTargetIcon();
return TARGET_ICON == null ? false : true;
}
public GeoPoint getLastGeoPoint() {
return mLocation;
}
public Location getLastLocation() {
return mLoc;
}
public void setLocation(final Location loc){
this.mLocation = TypeConverter.locationToGeoPoint(loc);
this.mAccuracy = loc.getAccuracy();
this.mBearing = loc.getBearing();
this.mSpeed = loc.getSpeed();
mLoc = loc;
}
public void setLocation(final GeoPoint geopoint){
this.mLocation = geopoint;
this.mAccuracy = 0;
this.mBearing = 0;
this.mSpeed = 0;
}
public void setTargetLocation(final GeoPoint geopoint) {
this.mTargetLocation = geopoint;
}
public GeoPoint getTargetLocation() {
return mTargetLocation;
}
public void correctScale(double sizeFactor, double sizeFactorGoogle) {
mScaleCorretion = Math.max(0, ((int) sizeFactor) - 1) + Math.max(0, ((int) sizeFactorGoogle) - 1);
if(mScaleCorretion < 0)
mScaleCorretion = 0;
}
// ===========================================================
// Methods from SuperClass/Interfaces
// ===========================================================
@Override
protected void onDrawFinished(Canvas c, TileView osmv) {
return;
}
@Override
public void onDraw(final Canvas c, final TileView osmv) {
if(this.mLocation != null){
final OpenStreetMapViewProjection pj = osmv.getProjection();
final Point screenCoords = new Point();
pj.toPixels(this.mLocation, screenCoords);
if(mNeedCircleDistance) {
mZoomLevel = osmv.getZoomLevel();
mTouchScale = osmv.mTouchScale;
int dist = SCALE[mUnits][Math.max(0, Math.min(19, mZoomLevel + 1 + (int)(mTouchScale > 1 ? Math.round(mTouchScale)-1 : -Math.round(1/mTouchScale)+1)) + mScaleCorretion)];
final GeoPoint center = osmv.getMapCenter();
if(mUnits == 1){
if(mZoomLevel < 11){
dist = (int) (dist * 1609.344);
} else {
dist = (int) (dist * 0.305);
}
}
final GeoPoint c2 = center.calculateEndingGlobalCoordinates(center, 90, dist);
final Point p = new Point();
pj.toPixels(c2, p);
mWidth = p.x - osmv.getWidth() / 2;
c.drawCircle(screenCoords.x, screenCoords.y, mWidth, this.mPaintCross);
c.drawCircle(screenCoords.x, screenCoords.y, mWidth * 2, this.mPaintCross);
c.drawCircle(screenCoords.x, screenCoords.y, mWidth * 3, this.mPaintCross);
c.drawCircle(screenCoords.x, screenCoords.y, mWidth * 4, this.mPaintCross);
}
if (mPrefAccuracy != 0
&& mSpeed <= 0.278
&& ((mAccuracy > 0 && mPrefAccuracy == 1) || (mPrefAccuracy > 1 && mAccuracy >= mPrefAccuracy))) {
int PixelRadius = (int) (osmv.mTouchScale * mAccuracy / ((float)METER_IN_PIXEL / (1 << osmv.getZoomLevel())));
c.drawCircle(screenCoords.x, screenCoords.y, PixelRadius, mPaintAccurasyFill);
c.drawCircle(screenCoords.x, screenCoords.y, PixelRadius, mPaintAccurasyBorder);
}
if(mLineToGPS) {
c.drawLine(screenCoords.x, screenCoords.y, osmv.getWidth() / 2, osmv.getHeight() / 2, mPaintLineToGPS);
final GeoPoint geo = pj.fromPixels(osmv.getWidth() / 2, osmv.getHeight() / 2);
final float dist = this.mLocation.distanceTo(geo);
final String lbl = String.format(Locale.UK, "%s %.1f�", mDf.formatDistance(dist), mLocation.bearingTo360(geo));
mLabelVw.setText(lbl);
mLabelVw.measure(0, 0);
mLabelVw.layout(0, 0, mLabelVw.getMeasuredWidth(), mLabelVw.getMeasuredHeight());
c.save();
c.translate(osmv.getWidth() / 2 - (screenCoords.x < osmv.getWidth() / 2 ? 0 : mLabelVw.getMeasuredWidth()), osmv.getHeight() / 2);
mLabelVw.draw(c);
c.restore();
}
if(mTargetLocation != null) {
final Point screenCoordsTarg = new Point();
pj.toPixels(this.mTargetLocation, screenCoordsTarg);
c.drawLine(screenCoords.x, screenCoords.y, screenCoordsTarg.x, screenCoordsTarg.y, mPaintLineToGPS);
}
c.save();
if (mSpeed <= 0.278) {
c.rotate(osmv.getBearing(), screenCoords.x, screenCoords.y);
if(getPersonIcon()){
c.drawBitmap(PERSON_ICON2, screenCoords.x - (int)(PERSON_ICON2.getWidth()/2), screenCoords.y - (int)(PERSON_ICON2.getHeight() / 2), mPaint);
};
} else {
if(getArrowIcon()){
c.rotate(mBearing, screenCoords.x, screenCoords.y);
c.drawBitmap(mArrow, screenCoords.x - (int)(mArrow.getWidth()/2), screenCoords.y - (int)(mArrow.getHeight() / 2), mPaint);
}
}
c.restore();
}
if(mTargetLocation != null) {
final OpenStreetMapViewProjection pj = osmv.getProjection();
final Point screenCoordsTarg = new Point();
pj.toPixels(this.mTargetLocation, screenCoordsTarg);
if(getTargetIcon())
c.drawBitmap(TARGET_ICON, screenCoordsTarg.x - (int)(TARGET_ICON.getWidth()/2), screenCoordsTarg.y - (int)(TARGET_ICON.getHeight() / 2), mPaint);
}
final int x = osmv.getWidth() / 2;
final int y = osmv.getHeight() / 2;
if(mNeedCrosshair){
c.drawLine(x - mCrossSize, y, x + mCrossSize, y, this.mPaintCross);
c.drawLine(x, y - mCrossSize, x, y + mCrossSize, this.mPaintCross);
}
}
}