package nav; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.graphics.Color; import android.location.Location; import com.ezio.multiwii.R; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.LocationSource; import com.google.android.gms.maps.model.BitmapDescriptor; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import com.google.android.gms.maps.model.Polyline; import com.google.android.gms.maps.model.PolylineOptions; public class MapHelperClass implements LocationSource { private final Context context; public final GoogleMap map; private Polyline WPPathPolyLine; public Marker HomeMarker; public Marker PositionHoldMarker; public Marker ModelMarker; final private float markerAnchorX = 0.17f; final private float markerAnchorY = 1f; public List<Marker> markers = new ArrayList<Marker>(); // public Circle CurrentWPCircle; private List<LatLng> FlyingPathPoints = new ArrayList<LatLng>(); private int FlyingPathPointsCount = 20; private Polyline FlightPathPolyLine; private OnLocationChangedListener onLocationChangedListener; private final int CircleAroundWPinMeters; private BitmapDescriptor ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_quadx); public MapHelperClass(Context context, GoogleMap map, int CircleAroundWPinMeters, int modelType) { this.context = context; this.map = map; this.CircleAroundWPinMeters = CircleAroundWPinMeters; setModelType(modelType); map.setMyLocationEnabled(true); map.setLocationSource(this); map.setMapType(GoogleMap.MAP_TYPE_SATELLITE); CleanMap(); } private void setModelType(int modelType) { final int TRI = 1; final int QUADP = 2; final int QUADX = 3; final int BI = 4; final int GIMBAL = 5; final int Y6 = 6; final int HEX6 = 7; final int FLYING_WING = 8; final int Y4 = 9; final int HEX6X = 10; final int OCTOX8 = 11; final int OCTOFLATX = 12; final int OCTOFLATP = 13; final int AIRPLANE = 14; final int HELI_120_CCPM = 15; final int HELI_90_DEG = 16; final int VTAIL4 = 17; final int HEX6H = 18; final int PPM_TO_SERVO = 19; final int DUALCOPTER = 20; final int SINGLECOPTER = 21; switch (modelType) { case TRI: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_tri); break; case QUADP: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_quadp); break; case QUADX: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_quadx); break; case BI: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_bi); break; case GIMBAL: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_quadx); break; case Y6: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_y6); break; case HEX6: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_hex6p); break; case FLYING_WING: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_fwing); break; case Y4: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_y4); break; case HEX6X: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_hex6x); break; case OCTOX8: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_octox8); break; case OCTOFLATX: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_octoflatx); break; case OCTOFLATP: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_oktoflatp); break; case AIRPLANE: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_airplane); break; case HELI_120_CCPM: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_heli); break; case HELI_90_DEG: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_heli); break; case VTAIL4: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_vtail4); break; case HEX6H: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_hex6p); break; case DUALCOPTER: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_bi); break; case SINGLECOPTER: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_heli); break; default: ModelIcon = BitmapDescriptorFactory.fromResource(R.drawable.marker_quadx); break; } } public void RedrawLines() { if (WPPathPolyLine != null) { WPPathPolyLine.remove(); WPPathPolyLine = null; } PolylineOptions polylineOptions = new PolylineOptions().color(Color.CYAN).width(4); for (Marker m : markers) { if (!m.getSnippet().contains("SET_POI")) { polylineOptions.add(m.getPosition()); } } WPPathPolyLine = map.addPolyline(polylineOptions); } public void DrawFlightPath(LatLng copterPositionLatLng) { if (FlyingPathPoints.size() == 0) { FlyingPathPoints.add(copterPositionLatLng); return; } if (gps2m(copterPositionLatLng.latitude, copterPositionLatLng.longitude, FlyingPathPoints.get(FlyingPathPoints.size() - 1).latitude, FlyingPathPoints.get(FlyingPathPoints.size() - 1).longitude) > 5) { FlyingPathPoints.add(copterPositionLatLng); if (FlyingPathPoints.size() > FlyingPathPointsCount) { FlyingPathPoints.remove(0); } if (FlightPathPolyLine != null) { FlightPathPolyLine.remove(); FlightPathPolyLine = null; } PolylineOptions polylineOptions = new PolylineOptions().color(Color.argb(100, 0, 255, 255)); for (LatLng p : FlyingPathPoints) { polylineOptions.add(p); } FlightPathPolyLine = map.addPolyline(polylineOptions); } } /** * * @return marker ID */ public String AddMarker(LatLng position, String title, String snippet, int action) { BitmapDescriptor IconColor;// = // BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE); switch (action) { case WaypointNav.WP_ACTION_WAYPOINT: IconColor = BitmapDescriptorFactory.fromResource(R.drawable.waypoint); break; case WaypointNav.WP_ACTION_POSHOLD_TIME: IconColor = BitmapDescriptorFactory.fromResource(R.drawable.poshold_time); break; case WaypointNav.WP_ACTION_POSHOLD_UNLIM: IconColor = BitmapDescriptorFactory.fromResource(R.drawable.poshold_unlim); break; case WaypointNav.WP_ACTION_LAND: IconColor = BitmapDescriptorFactory.fromResource(R.drawable.land); break; case WaypointNav.WP_ACTION_SET_POI: IconColor = BitmapDescriptorFactory.fromResource(R.drawable.poi); break; default: IconColor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE); break; } Marker m = map.addMarker(new MarkerOptions().position(position).draggable(true).icon(IconColor).anchor(markerAnchorX, markerAnchorY)); markers.add(m); m.setTitle(title); m.setSnippet(snippet); RedrawLines(); return m.getId(); } public void CleanMap() { markers = new ArrayList<Marker>(); map.clear(); addDefaultMarkersToMap(); } public void RemoveMarker(int position) { markers.get(position).remove(); markers.remove(position); } void addDefaultMarkersToMap() { LatLng mapCenter = map.getCameraPosition().target; HomeMarker = map.addMarker(new MarkerOptions().position(mapCenter).title("Home").icon(BitmapDescriptorFactory.fromResource(R.drawable.home)).draggable(false).anchor(markerAnchorX, markerAnchorY)); ModelMarker = map.addMarker(new MarkerOptions().position(mapCenter).title("Model").icon(ModelIcon).draggable(false).anchor(0.5f, 0.5f).flat(true)); PositionHoldMarker = map.addMarker(new MarkerOptions().position(mapCenter).title("PositionHold").icon(BitmapDescriptorFactory.fromResource(R.drawable.poshold)).draggable(false).anchor(markerAnchorX, markerAnchorY)); // CurrentWPCircle = map.addCircle(new // CircleOptions().center(mapCenter).radius(CircleAroundWPinMeters).fillColor(Color.argb(50, // 0, 255, 50))); // CurrentWPCircle.setStrokeWidth(2); } @Override public void activate(OnLocationChangedListener onLocationChangedListener) { this.onLocationChangedListener = onLocationChangedListener; } @Override public void deactivate() { this.onLocationChangedListener = null; } public static double gps2m(double lat_a, double lng_a, double lat_b, double lng_b) { Location locationA = new Location("point A"); locationA.setLatitude(lat_a); locationA.setLongitude(lng_a); Location locationB = new Location("point B"); locationB.setLatitude(lat_b); locationB.setLongitude(lng_b); return locationA.distanceTo(locationB); } public void SetCopterLocation(LatLng copterPositionLatLng, float head, float alt) { if (onLocationChangedListener != null) { Location copterLocation = new Location("CustomCopterLocation"); copterLocation.setLatitude(copterPositionLatLng.latitude); copterLocation.setLongitude(copterPositionLatLng.longitude); copterLocation.setBearing(head); copterLocation.setAccuracy(2); copterLocation.setAltitude(alt); ModelMarker.setPosition(copterPositionLatLng); ModelMarker.setRotation(head); onLocationChangedListener.onLocationChanged(copterLocation); } } static double FullCircleDegrees = 360d; static double HalfCircleDegrees = FullCircleDegrees / 2d; static double DegreesToRadians = Math.PI / HalfCircleDegrees; static double RadiansToDegrees = 1 / DegreesToRadians; public static LatLng GetPointGivenRadialAndDistance(LatLng center, double radius, double azimuth) { radius = radius * (1.56961231e-7); double lat1 = center.latitude * DegreesToRadians; double lng1 = center.longitude * DegreesToRadians; double lat = Math.asin((Math.sin(lat1) * Math.cos(radius)) + Math.cos(lat1) * Math.sin(radius) * Math.cos(azimuth * DegreesToRadians)); double lng = 0d; if (Math.cos(lat) == 0) { lng = lng1; } else { lng = ((lng1 + Math.PI - Math.asin(Math.sin(azimuth * DegreesToRadians) * Math.sin(radius) / Math.cos(lat1))) % (2 * Math.PI)) - Math.PI; } return new LatLng(lat * RadiansToDegrees, lng * RadiansToDegrees); } }