/*******************************************************************************
* Gaggle is Copyright 2010 by Geeksville Industries LLC, a California limited liability corporation.
*
* Gaggle is distributed under a dual license. We've chosen this approach because within Gaggle we've used a number
* of components that Geeksville Industries LLC might reuse for commercial products. Gaggle can be distributed under
* either of the two licenses listed below.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Commercial Distribution License
* If you would like to distribute Gaggle (or portions thereof) under a license other than
* the "GNU General Public License, version 2", contact Geeksville Industries. Geeksville Industries reserves
* the right to release Gaggle source code under a commercial license of its choice.
*
* GNU Public License, version 2
* All other distribution of Gaggle must conform to the terms of the GNU Public License, version 2. The full
* text of this license is included in the Gaggle source, see assets/manual/gpl-2.0.txt.
******************************************************************************/
package com.geeksville.location;
import org.andnav.osm.util.GeoPoint;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
public class ExtendedWaypoint extends Waypoint implements Comparable<ExtendedWaypoint> {
/**
* When used in a competition route, this number may be non zero (in meters)
*/
public int diameter = 0;
/**
* The vertical distance from the pilot (if pilot is higher this # will be
* negative)
*/
public int distanceFromPilotY;
/**
* The horizontal distance in meters from the pilot (or -1 for unknown)
*/
public int distanceFromPilotX = -1;
public GeoPoint geoPoint;
private WaypointDB db;
public enum Color {
SAFE, WARNING, DANGER
};
private Color color = Color.WARNING;
public ExtendedWaypoint(Cursor pts) {
super(pts);
init();
}
public ExtendedWaypoint(String name, double latitude, double longitude, int altitude, int type) {
this(name, latitude, longitude, altitude, 0, type);
}
public ExtendedWaypoint(String name, double latitude, double longitude, int altitude,
int diameter, int type) {
super(name, latitude, longitude, altitude, type);
this.diameter = diameter;
init();
}
void setOwner(WaypointDB db) {
this.db = db;
// Calc extended fields
recalculate();
}
private void init() {
geoPoint = new GeoPoint((int) (latitude * 1e6), (int) (longitude * 1e6));
}
/**
* Generate occasionally updated properties
*
* Used only by WaypointDB
*/
void recalculate() {
if (db.pilotLoc == null) {
distanceFromPilotX = -1;
distanceFromPilotY = -1;
color = Color.WARNING;
} else {
// FIXME - someday do all this math in udegrees
float mylat = (float) (db.pilotLoc.getLatitudeE6() / 1e6);
float mylong = (float) (db.pilotLoc.getLongitudeE6() / 1e6);
float destlat = (float) latitude;
float destlong = (float) longitude;
distanceFromPilotX = (int) LocationUtils.LatLongToMeter(mylat, mylong, destlat,
destlong);
distanceFromPilotY = altitude - db.pilotAlt;
color = calcColor();
}
}
/**
* We want points closest to the pilot to be sorted to the beginning of the
* collection (If we are missing distance info, compare by name)
*/
@Override
public int compareTo(ExtendedWaypoint another) {
if ((another.distanceFromPilotX == -1 || distanceFromPilotX == -1) && name != null
&& another.name != null)
return name.compareTo(another.name);
return distanceFromPilotX - another.distanceFromPilotX;
}
/**
* This waypoint has been changed and should be written back to the DB
*/
public void commit() {
db.updateWaypoint(this);
}
private float glideRatioFromPilot() {
// If we are below the point, we can't possibly glide to it
// If we don't know where the pilot is claim we can't glide to it
if (distanceFromPilotY >= 0)
return Float.POSITIVE_INFINITY;
return distanceFromPilotX / -distanceFromPilotY;
}
public String glideRatioString() {
if (distanceFromPilotX == -1)
return "---"; // We don't know where the pilot is
float ratio = glideRatioFromPilot();
// If we are below the point, we can't possibly glide to it
if (Float.isInfinite(ratio))
return "\u221E"; // infinity symbol
// FIXME - draw in yellow for warning or red for below glideslope
return String.format("%.1f", ratio);
}
/**
* How should we show this waypoint (SAFE, WARNING etc...)
*
* @return
*/
private Color calcColor() {
Color color;
// If we don't yet know the pilot location, assume warn
if (distanceFromPilotX == -1)
return Color.WARNING;
// If we are below the point, we can't possibly glide to it
if (distanceFromPilotY >= 0)
color = Color.DANGER;
else {
int distanceBelowMinAlt = (int) (distanceFromPilotY + db.minAltMargin);
int distanceBelowSafeAlt = (int) (distanceFromPilotY + db.minAltMargin + db.extraAltMargin);
float minGlideRatio = (distanceBelowMinAlt >= 0) ? Float.POSITIVE_INFINITY
: distanceFromPilotX
/ -distanceBelowMinAlt;
float safeGlideRatio = (distanceBelowSafeAlt >= 0) ? Float.POSITIVE_INFINITY
: distanceFromPilotX
/ -distanceBelowSafeAlt;
if (db.typicalGlideRatio >= safeGlideRatio)
color = Color.SAFE;
else if (db.typicalGlideRatio >= minGlideRatio)
color = Color.WARNING;
else
color = Color.DANGER;
}
return color;
}
/**
* How should we show this waypoint (SAFE, WARNING etc...)
*
* @return
*/
public Color getColor() {
return color;
}
/**
* Return an android color id for this waypoint
*
* @return
*/
public int getColorRGBA() {
return db.markerColors[getColor().ordinal()];
}
/**
* Get an icon that represents this waypoint
*
* @return
*
* We adjust color to show WARN or DANGER if the dest point is too
* high
*/
public Drawable getIcon() {
return getIcon(getColor());
}
/**
* Get an icon that represents this waypoint
*
* @return
*/
private Drawable getIcon(Color color) {
Drawable marker = db.markers[type.ordinal()][color.ordinal()];
// FIXME - return a drawable that has been modified to show
// distance/glide ratio
return marker;
}
}