Introduction
Originally, I implemented the idea of a radar-esque object as a UserControl for the purpose of parsing NMEA-structured GPS data and displaying the satellites in view. This worked well, but I've also wanted to write my first article for some time now, and this seemed like the time to do it. The Radar
class internally maintains a structure of RadarItem
implementations and draws them on radar. The position of the RadarItem
is determined by translating two values: Azimuth
and Elevation
.
Using the code
Class Diagram
Getting the Radar image
As shown in the Class Diagram, there are a few classes and an interface to work with in this implementation. First and foremost is the Radar
class. This is the main class for display of the radar image. There are two ways to get the Image
from the Radar
class:
- Use the
Radar.Image
member - Use the
ImageUpdateEventArgs.Image
passed by Radar.ImageUpdate
The following example demonstrates a combination of both for the purpose of showing the blank radar initially, not having to wait for an update to occur. The Radar.ImageUpdate
event is fired every time a change is made to the drawable elements of the Radar
class.
Radar radar;
private void frmMain_Load(object sender, EventArgs e)
{
Radar radar = new Radar(pictureBox1.Width);
pictureBox1.Image = radar.Image;
radar.ImageUpdate += new ImageUpdateHandler(radar_ImageUpdate);
}
void radar_ImageUpdate(object sender, ImageUpdateEventArgs e)
{
pictureBox1.Image = e.Image;
}
Color Options
The Radar
class has a few customizable colors in order to include the background colors (top and bottom of gradient) and the color of the lines drawn.
Radar radar = new Radar(pictureBox1.Width);
radar.CustomGradientColorTop = Color.FromArgb(0, 100, 0);
radar.CustomGradientColorBottom = Color.FromArgb(0, 40, 0);
radar.CustomLineColor = Color.FromArgb(0, 255, 0);
pictureBox1.Image = radar.Image;
Adding RadarItem objects to the Radar
There are three included classes that implement the RadarItem
interface. They are the CircleRadarItem
, SquareRadarItem
and TriangleRadarItem
objects. Feel free to create your own (see source code for examples) and email it to me!
RadarItem
s are differentiated from one another using the ID
member. This also allows for the Radar
object to update the position of a particular RadarItem
. The Radar
class contains an internal List<RadarItem>
that you can add items to using the Radar.AddItem
method. When you pass a RadarItem
with a pre-existing ID
, the RadarItem
in the List
is replaced with the new RadarItem
.
Radar radar = new Radar(pictureBox1.Width);
RadarItem item = new CircleRadarItem(2, 8, 45, 45);
pictureBox1.Image = radar.Image;
Extending the RadarItem Interface
public interface RadarItem : IComparable<RadarItem>
{
int ID { get; }
int Azimuth { get; set; }
int Elevation { get; set; }
int Height { get; set; }
int Width { get; set; }
DateTime Created { get; }
void DrawItem(Radar radar, Graphics g);
}
This is relatively straightforward. Just implement the interface and go to town! The DrawItem
method is called from the Radar
class. Supplied is the instance of the Radar
class, because of the AzEl2XY
method. In order to convert the Azimuth
and Elevation
to a PointF
, the algorithm has to be aware of the size of the Radar
. This method lives in the Radar
class for logical reasons and to not duplicate the code.
Also exposed through the Radar
class are the colors. I use Radar.CustomLineColor
as the color of my custom RadarItem
implementations. Also passed is an instance of Graphics
. This is the Graphics
that is used to draw directly on the Radar
. Although the RadarItem
interface requires the implementation of IComparable<RadarItem>
, it is not used for anything yet. The Created
member is also unused for the time being.
The Scan Line
Radar
includes a minor implementation of a "Scan Line" with fade. NOTE: When using the ScanLine, you will want to use the Radar.ImageUpdate
event to update the Image
on screen. This is because the Image
is constantly being updated.
Radar radar = new Radar(pictureBox1.Width);
radar.ImageUpdate += new ImageUpdateHandler(_radar_ImageUpdate);
radar.DrawScanInterval = 60;
radar.DrawScanLine = true;
Points of Interest
Particularly fun was adding the "Scan Line" to the Radar
as suggested by Ali, a coworker. I learned all about the GraphicsPath
object, as well as the PathGradientBrush
. See the code for details.
Radar
stores the background image separately in order to cut down on the drawing time. This image is updated every time the value of a background-related property is changed, i.e. CustomLineColor
.
History
- 17 August, 2007 -- Original version posted