public static String getTip(Context ctx, Preferences pref) { // generate tips sequentially String tips[] = ctx.getResources().getStringArray(R.array.Tips); int index = pref.getTipIndex(); if (index >= tips.length) { index = 0; } String ret = tips[index]; ret += ".\n" + ctx.getString(R.string.DisableTip); index++; pref.setTipIndex(index); return ret; }
private void startClosestAirportTask(double x, double y) { // We won't be doing the airport long press under certain circumstances if (mDraw) { return; } if (null != mClosestTask) { mClosestTask.cancel(true); } mLongTouchDestination = null; mClosestTask = new ClosestAirportTask(); double lon2, lat2; if (mPref.isTrackUp()) { double c_x = mOrigin.getOffsetX(mGpsParams.getLongitude()); double c_y = mOrigin.getOffsetY(mGpsParams.getLatitude()); double thetab = mGpsParams.getBearing(); double p[]; p = Helper.rotateCoord(c_x, c_y, thetab, x, y); lon2 = mOrigin.getLongitudeOf(p[0]); lat2 = mOrigin.getLatitudeOf(p[1]); } else { lon2 = mOrigin.getLongitudeOf(x); lat2 = mOrigin.getLatitudeOf(y); } mClosestTask.execute(lon2, lat2); }
/** * @param time * @param location * @param data */ public void putAirep(long time, String location, String data, DataSource db) { if (!mPref.useAdsbWeather()) { return; } String lonlat = db.findLonLat(location, Destination.BASE); if (null == lonlat) { return; } String tokens[] = lonlat.split(","); if (tokens.length != 2) { return; } Airep a = new Airep(); a.lon = Float.parseFloat(tokens[0]); a.lat = Float.parseFloat(tokens[1]); a.rawText = data; a.reportType = "PIREP"; Date dt = new Date(time); SimpleDateFormat sdf = new SimpleDateFormat("ddHHmm", Locale.getDefault()); sdf.setTimeZone(TimeZone.getTimeZone("gmt")); a.time = sdf.format(dt) + "Z"; a.timestamp = System.currentTimeMillis(); mAirep.put(location, a); }
/** * @param canvas * @param ctx */ private void drawTraffic(Canvas canvas, DrawingContext ctx) { Traffic.draw( ctx, mService.getTrafficCache().getTraffic(), mService.getTrafficCache().getOwnAltitude(), mGpsParams, mPref.getAircraftICAOCode(), null == mPointProjection); }
/** * * Draw the vertical approach slope indicator if we have a destination set * * @param canvas what to draw the data upon */ private void drawVASI(Canvas canvas) { if (mPointProjection == null && mErrorStatus == null) { if (mPref.getShowCDI()) { Destination dest = mService.getDestination(); if (dest != null) { mService.getVNAV().drawVNAV(canvas, getWidth(), getHeight(), dest); } } } }
/** * Draw the tracks to show our previous positions. If tracking is enabled, there is a linked list * of gps coordinates attached to this view with the most recent one at the end of that list. * Start at the end value to begin the drawing and as soon as we find one that is not in the range * of this display, we can assume that we're done. * * @param canvas * @param ctx */ private void drawTracks(Canvas canvas, DrawingContext ctx) { /* * Some pre-conditions that would prevent us from drawing anything */ if (mPref.isDrawTracks() && (null == mPointProjection)) { /* * Set the brush color and width */ mPaint.setColor(Color.CYAN); mPaint.setStrokeWidth(6 * mDipToPix); mPaint.setStyle(Paint.Style.FILL); mService .getKMLRecorder() .getShape() .drawShape(canvas, mOrigin, mScale, mMovement, mPaint, mPref.isNightMode(), true); } }
/** * @param time * @param block * @param empty * @param isConus * @param data * @param cols * @param rows */ public void putImg( long time, int block, int empty[], boolean isConus, int data[], int cols, int rows) { if (!mPref.useAdsbWeather()) { return; } if (isConus) { mNexradConus.putImg(time, block, empty, isConus, data, cols, rows); } else { mNexrad.putImg(time, block, empty, isConus, data, cols, rows); } }
/** * @param canvas * @param ctx */ private void drawLayers(Canvas canvas, DrawingContext ctx) { if (mLayerType == null || null != mPointProjection || 0 == mPref.showLayer()) { return; } if (ctx.pref.useAdsbWeather()) { if (mLayerType.equals("NEXRAD")) { NexradBitmap.draw( ctx, mService.getAdsbWeather().getNexrad(), mService.getAdsbWeather().getNexradConus(), null == mPointProjection); } else if (mLayerType.equals("METAR")) { AdsbWeatherCache.drawMetars( ctx, mService.getAdsbWeather().getAllMetars(), null == mPointProjection); } } else { if (mLayerType.equals("NEXRAD")) { // draw nexrad mLayer = mService.getRadarLayer(); } else if (mLayerType.equals("METAR")) { // draw metar flight catergory mLayer = ctx.service.getMetarLayer(); } else { mLayer = null; return; } /* * layer is way too old. */ if (mLayer.isOld(ctx.pref.getExpiryTime())) { return; } mPaint.setAlpha(mPref.showLayer()); mLayer.draw(canvas, mPaint, mOrigin); mPaint.setAlpha(255); } }
/** * Draws concentric circles around the current aircraft position showing distance. author: rwalker * * @param canvas upon which to draw the circles */ private void drawDistanceRings(Canvas canvas) { /* * Some pre-conditions that would prevent us from drawing anything */ if (null != mPointProjection) { return; } // Tell the rings to draw themselves mService .getDistanceRings() .draw(canvas, mOrigin, mScale, mMovement, mPref.isTrackUp(), mGpsParams); }
/** * @param time * @param location * @param data */ public void putTaf(long time, String location, String data) { if (!mPref.useAdsbWeather()) { return; } Taf f = new Taf(); f.rawText = location + " " + data; f.stationId = location; Date dt = new Date(time); SimpleDateFormat sdf = new SimpleDateFormat("ddHHmm", Locale.getDefault()); sdf.setTimeZone(TimeZone.getTimeZone("gmt")); f.time = sdf.format(dt) + "Z"; f.timestamp = System.currentTimeMillis(); mTaf.put(location, f); }
/** * @param time * @param location * @param data */ public void putMetar(long time, String location, String data, String flightCategory) { if (!mPref.useAdsbWeather()) { return; } Metar m = new Metar(); m.rawText = location + " " + data; m.stationId = location; Date dt = new Date(time); SimpleDateFormat sdf = new SimpleDateFormat("ddHHmm", Locale.getDefault()); sdf.setTimeZone(TimeZone.getTimeZone("gmt")); m.time = sdf.format(dt) + "Z"; m.flightCategory = flightCategory; m.timestamp = System.currentTimeMillis(); mMetar.put(location, m); mMetarQueue.insertMetarInQueue(m); // This will slowly make a metar map }
/** * * Draw the edge distance markers if configured to do so * * @param canvas what to draw them on */ private void drawEdgeMarkers(Canvas canvas) { if (mPref.isShowEdgeTape()) { if (mPointProjection == null) { int x = (int) (mOrigin.getOffsetX(mGpsParams.getLongitude())); int y = (int) (mOrigin.getOffsetY(mGpsParams.getLatitude())); float pixPerNm = mOrigin.getPixelsInNmAtLatitude(1, mGpsParams.getLatitude()); mService .getEdgeTape() .draw( canvas, mScale, pixPerNm, x, y, (int) mService.getInfoLines().getHeight(), getWidth(), getHeight()); } } }
/** * @param time * @param location * @param data */ public void putWinds(long time, String location, String data) { if (!mPref.useAdsbWeather()) { return; } WindsAloft w = new WindsAloft(); w.station = location; /* * Clear garbage spaces etc. Convert to Avare format */ String winds[] = data.split(","); if (winds.length < 9) { return; } w.w3k = winds[0]; w.w6k = winds[1]; w.w9k = winds[2]; w.w12k = winds[3]; w.w18k = winds[4]; w.w24k = winds[5]; w.w30k = winds[6]; w.w34k = winds[7]; w.w39k = winds[8]; Date dt = new Date(time); SimpleDateFormat sdf = new SimpleDateFormat("ddHHmm", Locale.getDefault()); sdf.setTimeZone(TimeZone.getTimeZone("gmt")); w.time = sdf.format(dt) + "Z"; /* * Find lon/lat of station */ float coords[] = new float[2]; if (!Stations.getStationLocation(location, coords)) { return; } w.lon = coords[0]; w.lat = coords[1]; w.timestamp = System.currentTimeMillis(); mWinds.put(location, w); }
/* * ALL ADSB weather should be kaput after expiry */ public void sweep() { long now = System.currentTimeMillis(); int expiry = mPref.getExpiryTime() * 60 * 1000; /* * Go at them one by one * LinkedList saves against concurrent modification exception */ LinkedList<String> keys; /* * Winds */ keys = new LinkedList<String>(); for (String key : mWinds.keySet()) { WindsAloft w = mWinds.get(key); long diff = (now - w.timestamp) - expiry; if (diff > 0) { keys.add(key); } } for (String key : keys) { mWinds.remove(key); } /* * Taf */ keys = new LinkedList<String>(); for (String key : mTaf.keySet()) { Taf f = mTaf.get(key); long diff = (now - f.timestamp) - expiry; if (diff > 0) { keys.add(key); } } for (String key : keys) { mTaf.remove(key); } /* * Metar */ keys = new LinkedList<String>(); for (String key : mMetar.keySet()) { Metar m = mMetar.get(key); long diff = (now - m.timestamp) - expiry; if (diff > 0) { keys.add(key); } } for (String key : keys) { mMetar.remove(key); } /* * Airep */ keys = new LinkedList<String>(); for (String key : mAirep.keySet()) { Airep a = mAirep.get(key); long diff = (now - a.timestamp) - expiry; if (diff > 0) { keys.add(key); } } for (String key : keys) { mAirep.remove(key); } /* * Nexrad */ LinkedList<Integer> keyi = new LinkedList<Integer>(); SparseArray<NexradBitmap> img = mNexrad.getImages(); for (int i = 0; i < img.size(); i++) { NexradBitmap n = img.valueAt(i); long diff = (now - n.timestamp) - expiry; if (diff > 0) { keyi.add(img.keyAt(i)); } } for (Integer key : keyi) { img.remove(key); } }
/* (non-Javadoc) * @see android.view.View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent) */ @Override public boolean onTouch(View view, MotionEvent e) { boolean bPassToGestureDetector = true; if (e.getAction() == MotionEvent.ACTION_UP) { /** Rubberbanding */ rubberBand(e.getX(), e.getY(), true); /* * Drag stops for rubber band */ mDragPlanPoint = -1; /* * Do not draw point. Only when long press and down. */ mPointProjection = null; /* * Now that we have moved passed the macro level, re-query for new tiles. * Do not query repeatedly hence check for mFactor = 1 */ if (mMacro != mScale.getMacroFactor()) { loadTiles(); } } else if (e.getAction() == MotionEvent.ACTION_DOWN) { if (mService != null) { /* * Find if this is close to a plan point. Do rubber banding if true * This is where rubberbanding starts */ if (mService.getPlan() != null && mDragPlanPoint < 0 && mPref.allowRubberBanding()) { double lon = mOrigin.getLongitudeOf(e.getX()); double lat = mOrigin.getLatitudeOf(e.getY()); mDragPlanPoint = mService.getPlan().findClosePointId(lon, lat, mScale.getScaleFactor()); mDragStartedX = e.getX(); mDragStartedY = e.getY(); } } mGestureCallBack.gestureCallBack(GestureInterface.TOUCH, (LongTouchDestination) null); // Remember this point so we can make sure we move far enough before losing the long press mDoCallbackWhenDone = false; mDownFocusPoint = getFocusPoint(e); startClosestAirportTask(e.getX(), e.getY()); } else if (e.getAction() == MotionEvent.ACTION_MOVE) { if (mDownFocusPoint != null) { Point fp = getFocusPoint(e); final int deltaX = fp.x - mDownFocusPoint.x; final int deltaY = fp.y - mDownFocusPoint.y; int distanceSquare = (deltaX * deltaX) + (deltaY * deltaY); bPassToGestureDetector = distanceSquare > mTouchSlopSquare; } // Rubberbanding, intermediate rubberBand(e.getX(), e.getY(), false); } if (bPassToGestureDetector) { // Once we break out of the square or stop the long press, keep sending if (e.getAction() == MotionEvent.ACTION_MOVE || e.getAction() == MotionEvent.ACTION_UP) { mDownFocusPoint = null; mPointProjection = null; if (mClosestTask != null) { mClosestTask.cancel(true); } } mGestureDetector.onTouchEvent(e); } return mMultiTouchC.onTouchEvent(e, mScale.getMaxScale(), mScale.getMinScale(), mMacro); }
// Display all of the user defined waypoints if configured to do so private void drawUserDefinedWaypoints(Canvas canvas, DrawingContext ctx) { if (mPointProjection == null) { mService.getUDWMgr().draw(canvas, mPref.isTrackUp(), mGpsParams, mFace, mOrigin); } }
/** * Update the current speed, lat, lon, that will update ETA, distance and bearing to the * destination * * @param params */ public void updateTo(GpsParams params) { /* */ double mLon = params.getLongitude(); double mLat = params.getLatitude(); double speed = params.getSpeed(); mDeclination = params.getDeclinition(); if (!mFound) { return; } if (!mInited) { mLonInit = mLon; mLatInit = mLat; mInited = true; } /* * Project and find distance */ Projection p = new Projection(mLon, mLat, mLond, mLatd); mDistance = p.getDistance(); mBearing = p.getBearing(); // in flying mode, calculate time based on ground speed from GPS mGroundSpeed = speed; mWca = 0; mCrs = mBearing; if (mPref.isSimulationMode()) { double ws = 0; double wd = 0; if (mWinds != null) { double winds[] = mWinds.getWindAtAltitude(params.getAltitude()); ws = winds[0]; wd = winds[1]; } // in sim mode, do planning with winds speed = mPref.getAircraftTAS(); // in sim mode, use preferred TAS // from aviation formulary double hd = mBearing; mGroundSpeed = Math.sqrt( ws * ws + speed * speed - 2 * ws * speed * Math.cos((hd - wd) * Math.PI / 180.0)); mWca = -Math.toDegrees( Math.atan2( ws * Math.sin((hd - wd) * Math.PI / 180.0), speed - ws * Math.cos((hd - wd) * Math.PI / 180.0))); mCrs = (hd + mWca + 360) % 360; } else if (mPref.useBearingForETEA() && (!mService.getPlan().isActive())) { // This is just when we have a destination set and no plan is active // We can't assume that we are heading DIRECTLY for the destination, so // we need to figure out the multiply factor by taking the COS of the difference // between the bearing and the heading. double angDif = Helper.angularDifference(params.getBearing(), mBearing); double xFactor = 1; // If the difference is 90 or greater, then ETE means nothing as we are not // closing on the target if (angDif < 90) { // Calculate the actual relative speed closing on the target xFactor = Math.cos(angDif * Math.PI / 180); } mGroundSpeed *= xFactor; } /* * ETA when speed != 0 */ mEte = Helper.calculateEte(mDistance, mGroundSpeed, 0, true); if (mGroundSpeed == 0) { mEteSec = Long.MAX_VALUE; mFuelGallons = Float.MAX_VALUE; mFuel = "-.-"; } else { mEteSec = (long) (mDistance / mGroundSpeed * 3600); mFuelGallons = (float) mEteSec / 3600 * mPref.getFuelBurn(); mFuel = String.valueOf((float) Math.round(mFuelGallons * 10.f) / 10.f); } // Calculate the time of arrival at our destination. We SHOULD be taking in to account // the timezone at that location mEta = Helper.calculateEta(Calendar.getInstance().getTimeZone(), mDistance, mGroundSpeed); }
/** @param canvas Does pretty much all drawing on screen */ private void drawMap(Canvas canvas) { if (mService == null) { return; } // If our track is supposed to be at the top, save the current // canvas and rotate it based upon our bearing if we have one boolean bRotated = false; if (mPref.isTrackUp() && (mGpsParams != null)) { bRotated = true; canvas.save(); /* * Rotate around current position */ float x = (float) mOrigin.getOffsetX(mGpsParams.getLongitude()); float y = (float) mOrigin.getOffsetY(mGpsParams.getLatitude()); canvas.rotate(-(int) mGpsParams.getBearing(), x, y); } DrawingContext ctx = new DrawingContext(); ctx.service = mService; ctx.canvas = canvas; ctx.context = mContext; ctx.dip2pix = mDipToPix; ctx.movement = mMovement; ctx.origin = mOrigin; ctx.paint = mPaint; ctx.textPaint = mMsgPaint; ctx.scale = mScale; ctx.pan = mPan; ctx.pref = mPref; ctx.runwayPaint = mRunwayPaint; ctx.view = this; // Call the draw routines for the items that rotate with // the chart drawTiles(canvas, ctx); drawLayers(canvas, ctx); drawDrawing(canvas, ctx); drawCapGrids(canvas, ctx); drawTraffic(canvas, ctx); drawTFR(canvas, ctx); drawGameTFRs(ctx); drawShapes(canvas, ctx); drawAirSigMet(canvas, ctx); drawTracks(canvas, ctx); drawTrack(canvas, ctx); drawRunways(canvas, ctx); drawAircraft(canvas, ctx); drawUserDefinedWaypoints(canvas, ctx); // Restore the canvas to be upright again if (true == bRotated) { canvas.restore(); } // Now draw the items that do NOT rotate with the chart drawDistanceRings(canvas); drawCDI(canvas); drawVASI(canvas); drawStatusLines(canvas); drawEdgeMarkers(canvas); // Must be after the infolines drawNavComments(canvas); }
// Display cap grids private void drawCapGrids(Canvas canvas, DrawingContext ctx) { if (mPointProjection == null && mPref.showCAPGrids()) { mService.getCap().draw(canvas, mOrigin, mScale); } }
/* (non-Javadoc) * @see com.ds.avare.MultiTouchController.MultiTouchObjectCanvas#setPositionAndScale(java.lang.Object, com.ds.avare.MultiTouchController.PositionAndScale, com.ds.avare.MultiTouchController.PointInfo) */ public boolean setPositionAndScale( Object obj, PositionAndScale newObjPosAndScale, PointInfo touchPoint) { touchPointChanged(touchPoint); if (false == mCurrTouchPoint.isMultiTouch()) { /* * Do not move on drag */ if (mDragPlanPoint >= 0) { return true; } /* * Do not move on multitouch */ if (mDraw && mService != null) { float x = mCurrTouchPoint.getX() * mScale.getScaleFactor(); float y = mCurrTouchPoint.getY() * mScale.getScaleFactor(); /* * Threshold the drawing so we do not generate too many points */ if (mPref.isTrackUp()) { double thetab = mGpsParams.getBearing(); double p[] = new double[2]; double c_x = mOrigin.getOffsetX(mGpsParams.getLongitude()); double c_y = mOrigin.getOffsetY(mGpsParams.getLatitude()); p = Helper.rotateCoord(c_x, c_y, thetab, x, y); mService.getDraw().addPoint((float) p[0], (float) p[1], mOrigin); } else { mService.getDraw().addPoint(x, y, mOrigin); } return true; } // Pan if (mPan.setMove(newObjPosAndScale.getXOff(), newObjPosAndScale.getYOff())) { /* * Query when we have moved one tile. This will happen in background. */ loadTiles(); } } else { // Zooming does not change drag mDragPlanPoint = -1; /* * on double touch find distance and bearing between two points. */ if (mPointProjection == null) { double x0 = mCurrTouchPoint.getXs()[0]; double y0 = mCurrTouchPoint.getYs()[0]; double x1 = mCurrTouchPoint.getXs()[1]; double y1 = mCurrTouchPoint.getYs()[1]; double lon0, lat0, lon1, lat1; // convert to origin coord if Trackup if (mPref.isTrackUp()) { double c_x = mOrigin.getOffsetX(mGpsParams.getLongitude()); double c_y = mOrigin.getOffsetY(mGpsParams.getLatitude()); double thetab = mGpsParams.getBearing(); double p0[], p1[]; p0 = Helper.rotateCoord(c_x, c_y, thetab, x0, y0); p1 = Helper.rotateCoord(c_x, c_y, thetab, x1, y1); lon0 = mOrigin.getLongitudeOf(p0[0]); lat0 = mOrigin.getLatitudeOf(p0[1]); lon1 = mOrigin.getLongitudeOf(p1[0]); lat1 = mOrigin.getLatitudeOf(p1[1]); } else { lon0 = mOrigin.getLongitudeOf(x0); lat0 = mOrigin.getLatitudeOf(y0); lon1 = mOrigin.getLongitudeOf(x1); lat1 = mOrigin.getLatitudeOf(y1); } mPointProjection = new Projection(lon0, lat0, lon1, lat1); } /* * Clamp scaling. */ mScale.setScaleFactor(newObjPosAndScale.getScale()); } updateCoordinates(); invalidate(); return true; }