Skip to content
Open
23 changes: 12 additions & 11 deletions ExtLibs/ArduPilot/Mavlink/MAVLinkInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5166,25 +5166,26 @@ public async Task<MAVLinkMessage> readPacketAsync()
// adsb packets are forwarded and can be from any sysid/compid
if (msgid == (byte)MAVLINK_MSG_ID.ADSB_VEHICLE)
{
var adsb = message.ToStructure<mavlink_adsb_vehicle_t>();
var adsbMessage = message.ToStructure<mavlink_adsb_vehicle_t>();

var id = adsb.ICAO_address.ToString("X5");
var id = adsbMessage.ICAO_address.ToString("X5");

if (_UpdateADSBPlanePosition != null)
_UpdateADSBPlanePosition(this, new adsb.PointLatLngAltHdg(
adsb.lat / 1e7,
adsb.lon / 1e7,
adsb.altitude / 1000,
adsb.heading * 0.01f,
adsb.hor_velocity,
adsbMessage.lat / 1e7,
adsbMessage.lon / 1e7,
adsbMessage.altitude / 1000,
adsbMessage.heading * 0.01f,
adsbMessage.hor_velocity,
id,
DateTime.Now
)
{
CallSign = Encoding.UTF8.GetString(adsb.callsign),
Squawk = adsb.squawk,
Raw = adsb,
VerticalSpeed = adsb.ver_velocity,
CallSign = Encoding.UTF8.GetString(adsbMessage.callsign),
Squawk = adsbMessage.squawk,
Raw = adsbMessage,
VerticalSpeed = adsbMessage.ver_velocity,
Category = adsb.GetEmitterCategoryShort((ADSB_EMITTER_TYPE)adsbMessage.emitter_type),
}
);
}
Expand Down
153 changes: 143 additions & 10 deletions ExtLibs/Maps/GMapMarkerADSBPlane.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,48 @@
using System;
using System.Drawing;
using GMap.NET;
using GMap.NET.Drawing.Properties;
using GMap.NET.WindowsForms;

namespace MissionPlanner.Maps
{
[Serializable]
public class GMapMarkerADSBPlane : GMapMarker
{
private static readonly Bitmap icong = new Bitmap(global::MissionPlanner.Maps.Resources.FW_icons_2013_logos_01,
new Size(40, 40));
// The images we're using are 72x72, so we'll use that as the size
private static readonly Size size = new Size(72, 72);

private static readonly Bitmap iconr = new Bitmap(global::MissionPlanner.Maps.Resources.FW_icons_2013_logos_011,
new Size(40, 40));
// Images retrieved from tar1090 sprites: https://github.com/wiedehopf/tar1090/blob/master/html/images/sprites.png
private static readonly Bitmap adsb_unknown = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_unknown, size);
private static readonly Bitmap adsb_light = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_light, size);
private static readonly Bitmap adsb_small = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_small, size);
private static readonly Bitmap adsb_large = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_large, size);
private static readonly Bitmap adsb_heavy = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_heavy, size);
private static readonly Bitmap adsb_highly_manuv = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_highly_manuv, size);
private static readonly Bitmap adsb_rotocraft = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_rotocraft, size);
//private static readonly Bitmap adsb_glider = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_glider, size);
private static readonly Bitmap adsb_lighter_air = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_balloon, size);
private static readonly Bitmap adsb_parachute = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_parachute, size);
//private static readonly Bitmap adsb_ultralight = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_ultralight, size);
private static readonly Bitmap adsb_uav = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_uav, size);
private static readonly Bitmap adsb_emergency_surface = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_emergency_surface, size);
private static readonly Bitmap adsb_service_surface = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_service_surface, size);
private static readonly Bitmap adsb_point_obstacle = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_balloon, size); // point obstacles are used for balloons

private static readonly Bitmap icono = new Bitmap(global::MissionPlanner.Maps.Resources.FW_icons_2013_logos_012,
new Size(40, 40));

public float heading = 0;
public AlertLevelOptions AlertLevel = AlertLevelOptions.Green;
public float DrawScale = 0.5f;

// Cache the last drawn data to avoid re-coloring every frame
private Bitmap lastDrawn = null;
// Store the last alert level to decide whether to redraw
private AlertLevelOptions lastAlertLevel = AlertLevelOptions.Green;
private MAVLink.ADSB_EMITTER_TYPE lastEmitterCategory = MAVLink.ADSB_EMITTER_TYPE.NO_INFO;
private bool lastIsOnGround = true;

public MAVLink.ADSB_EMITTER_TYPE EmitterCategory { get; set; }
public bool IsOnGround { get; set; }

public enum AlertLevelOptions
{
Expand All @@ -32,10 +56,33 @@ public GMapMarkerADSBPlane(PointLatLng p, float heading, AlertLevelOptions alert
{
this.AlertLevel = alert;
this.heading = heading;
Size = icong.Size;
Size = size;
Offset = new Point(Size.Width / -2, Size.Height / -2);
}

private static void ColorSprite(Bitmap bitmap, Color fillColor)
{
int width = bitmap.Width;
int height = bitmap.Height;

bool IsWhite(Color pixel) => pixel.R == 255 && pixel.G == 255 && pixel.B == 255 && pixel.A != 0;

// Iterate through every pixel in the image
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Color pixel = bitmap.GetPixel(x, y);

// If the pixel is white, color it with the fill color
if (IsWhite(pixel))
{
bitmap.SetPixel(x, y, fillColor);
}
}
}
}

public override void OnRender(IGraphics g)
{
var temp = g.Transform;
Expand All @@ -51,18 +98,104 @@ public override void OnRender(IGraphics g)
{
}

bool needsRedraw = lastDrawn == null || lastAlertLevel != AlertLevel || lastEmitterCategory != EmitterCategory || lastIsOnGround != IsOnGround;
if (!needsRedraw)
{
g.ScaleTransform(DrawScale, DrawScale);
g.DrawImageUnscaled(lastDrawn, lastDrawn.Width / -2, lastDrawn.Height / -2);
g.Transform = temp;
return;
}

// Set the icon based on emitter category
Bitmap bitmap = adsb_unknown;
DrawScale = 0.5f;

switch (this.EmitterCategory)
{
case MAVLink.ADSB_EMITTER_TYPE.NO_INFO:
bitmap = adsb_unknown;
break;
case MAVLink.ADSB_EMITTER_TYPE.LIGHT:
bitmap = adsb_light;
break;
case MAVLink.ADSB_EMITTER_TYPE.SMALL:
bitmap = adsb_small;
break;
case MAVLink.ADSB_EMITTER_TYPE.LARGE:
bitmap = adsb_large;
DrawScale *= 1.25f;
break;
case MAVLink.ADSB_EMITTER_TYPE.HEAVY:
bitmap = adsb_heavy;
DrawScale *= 1.5f;
break;
case MAVLink.ADSB_EMITTER_TYPE.HIGH_VORTEX_LARGE:
bitmap = adsb_heavy;
DrawScale *= 1.5f;
break;
case MAVLink.ADSB_EMITTER_TYPE.HIGHLY_MANUV:
bitmap = adsb_highly_manuv;
break;
case MAVLink.ADSB_EMITTER_TYPE.ROTOCRAFT:
bitmap = adsb_rotocraft;
break;
case MAVLink.ADSB_EMITTER_TYPE.GLIDER:
bitmap = adsb_lighter_air;
break;
case MAVLink.ADSB_EMITTER_TYPE.PARACHUTE:
bitmap = adsb_parachute;
break;
case MAVLink.ADSB_EMITTER_TYPE.ULTRA_LIGHT:
bitmap = adsb_lighter_air;
break;
case MAVLink.ADSB_EMITTER_TYPE.UAV:
bitmap = adsb_uav;
break;
case MAVLink.ADSB_EMITTER_TYPE.SPACE:
//???
break;
case MAVLink.ADSB_EMITTER_TYPE.EMERGENCY_SURFACE:
bitmap = adsb_emergency_surface;
break;
case MAVLink.ADSB_EMITTER_TYPE.SERVICE_SURFACE:
bitmap = adsb_service_surface;
break;
case MAVLink.ADSB_EMITTER_TYPE.POINT_OBSTACLE:
bitmap = adsb_point_obstacle;
break;
}
lastEmitterCategory = EmitterCategory;
bitmap = (Bitmap)bitmap.Clone();
g.ScaleTransform(DrawScale, DrawScale);
// Set the color based on alert level
var fillColor = Color.Green;
switch (AlertLevel)
{
case AlertLevelOptions.Green:
g.DrawImageUnscaled(icong, icong.Width / -2, icong.Height / -2);
fillColor = Color.Green;
break;
case AlertLevelOptions.Orange:
g.DrawImageUnscaled(icono, icono.Width / -2, icono.Height / -2);
fillColor = Color.Orange;
break;
case AlertLevelOptions.Red:
g.DrawImageUnscaled(iconr, iconr.Width / -2, iconr.Height / -2);
fillColor = Color.Red;
break;
}
lastAlertLevel = AlertLevel;

if (IsOnGround)
{
fillColor = Color.DarkGray;
fillColor = Color.FromArgb(128, fillColor);
}
lastIsOnGround = IsOnGround;

ColorSprite(bitmap, fillColor);

g.DrawImageUnscaled(bitmap, bitmap.Width / -2, bitmap.Height / -2);

lastDrawn = (Bitmap)bitmap.Clone();

g.Transform = temp;
}
Expand Down
132 changes: 131 additions & 1 deletion ExtLibs/Maps/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading