Click here to Skip to main content
Email Password   helpLost your password?

Screenshot - Radar1.jpg

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

Screenshot - Radar2.jpg

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:

  1. Use the Radar.Image member
  2. 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)
{
    // create a new instance of the Radar class

    Radar radar = new Radar(pictureBox1.Width); 
    // hint: use a square PictureBox


    // display the base image initially

    pictureBox1.Image = radar.Image;

    // add a handler for the ImageUpdate event

    radar.ImageUpdate += new ImageUpdateHandler(radar_ImageUpdate);
}

void radar_ImageUpdate(object sender, ImageUpdateEventArgs e)
{
    // display the updated image

    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);

// change the colors of the radar

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!

RadarItems 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);

// Arguments:

//   1. ID

//   2. Size

//   3. Azimuth

//   4. Elevation

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; // in millisecs

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

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralTracking targets
chakri4
8:06 11 Mar '10  
I had used your code and it is very useful for my project and another thing here is: we have to get the azimuth and elevation values through network, that is,some other radar will send which it acts as a client(take for example).The display is like a server which will display targets.Here targets values continuously varies based on time interval.

Is it possible to track the targets continuously and show it on display?

I have one idea about this and it is good or not,i don't know.
First value comes we show a point and next value will come after some time interval and this point will also be displayed.In between these points a line or dotted line is to be drawn.Likewise is it possible to display all points with connected lines?

Reply me soon it's urgent.
Generalis it possible to add tooltipe to radar item ??
yoramn@cti2.com
4:31 20 May '09  
very nice ..
is it possible to add tooltipe to radar item ??

Thanks
GeneralRe: is it possible to add tooltipe to radar item ??
ahmed eid ahmed
0:03 13 Feb '10  
how can I add tool tip to radar item
Questionabout cpu usage problem
webgiser
2:59 5 Mar '09  
Hi, Jim!

Perfect app!

I've tried your app, but i found the cpu usage keeps climbing when ur app running. I think there's something wrong with your algorithm.

Edward Roll eyes
GeneralSector Scan
Stellenbosch
3:42 3 Dec '08  
Hi!

I'm trying use ur code to create a sector scan! and I have some questions please! Hope you can help me!

How could I make the ScanLine starts from a certain point?? It always starts from 90 Degree!!
ans Is there a way to do ScanLine between 90 Degree and 0 Degree??


Thanx in advance and Excuse my pooor English! Smile
QuestionMemory hog
ebenedict
8:31 20 Oct '08  
Jim, when I run both your test code and code of my own using the radar code it seems to grow in memory size by the second until reaching some sort of threshold then returning to the initial size.

ex- upon start (around 16MB) then steadily grows to around 80MB then back to around 20MB and repeats this cycle until closed.

Any help on what is causing this growth loop? I already implemented your code change to the addItem() method. Maybe something in the drawing code? copying the base image causing trouble?

just some thoughts.

Anybody have any ideas?

EJB-
AnswerRe: Memory hog
JimBlaney
18:14 22 Oct '08  
EJB-

I'm noticing the same thing... The only thing that I can think of off the top of my head would be that this is the garbage collector in action.

I'm going to experiment with it over the next week or so. I'm wondering what would happen if I re-wrote this as a UserControl, versus the current "renderer" model. I'm also wondering what would happen if I generated the picture in a reactive sense -- right now it's proactive, as an event pushes the Image to the parent form. I don't think that the latter is the best way to implement this.

Jim Blaney
GeneralRe: Memory hog
ebenedict
17:35 24 Oct '08  
Jim,

I'm that experienced in the "drawing" aspect of C# but I'm curious if it's possible to draw the "radar" once (and only once) in it's own layer?

And then maybe draw the "items" on a separate layer? Like I said, this isn't my area. Just a thought.

Also, is it possible to dispose of the current radar image when we are done with it?

EJB-
GeneralRe: Memory hog
JimBlaney
6:18 25 Oct '08  
If you look in the Radar class, you'll see that I draw the background image once and only once, cache it, and then clone it to draw the RadarItems on top of for the final output image. I understand what you're saying about exposing the background image and the overlays as two separate images. But, you're eventually going to have to combine them, be it in the Radar class or elsewhere in your application.

Jim
Generalnot a real radar
_marsim_
6:50 11 Jun '08  
A real radar has a scaning line that it's used to let the user view the objects on the PPI.

In few words the scanning line is related to one or more spinning radars and represents the electromagnetic ray that when meets an object it reveals it on the display. So when the spinning line goes over the represented object it is visible at maximum and when the line moves away from the object is faded progressively until the line goes on it again. In your case the spinning line has no mean because objects are always visible.
GeneralRe: not a real radar
Lewis Bowman
5:58 21 Jan '09  
Just a p.s. to this comment

All modern radar extrapolate positionals and the fading thing is a myth since the very early 90's.
GeneralRe: not a real radar
_marsim_
7:32 21 Jan '09  
Really! I didn't wknow. My experience is based on the HAWK SAM System that is a system that is before the '90s Smile
GeneralRadar
My name dammit !
21:40 22 Aug '07  
Hey Jim.
Nice work. I like the way you used the PathGradientBrush. ! It would be cool if the tail faded away into transparency. Later. Jim.
GeneralTerminology [modified]
Mark Treadwell
18:34 18 Aug '07  
The position of something from your radar is actually described using a bearing (aka "azimuth"), range(aka "distance"), and altitude (aka "elevation" or "height") to fit within a polar coordinate system. Your use of azimuth, elevation and height is not correct.

Note that radars in reality measure "slant range" which is the straight line distance at some angle above the horizontal from antenna to object, but ignoring that for this purpose is reasonable.

Mark Treadwell
Special Enhancements

GeneralRe: Terminology
BubbaJonBoy
4:09 21 Aug '07  
And in addition to the comments above in a real PPI (plane position indicator is the actual name of a "radar" display) the sweep is an electron beam that "paints" the target on the phosphors as it goes around in synchronization with the rotation of the radar antenna. In your implementation the targets wander in real time irrespective of the sweep position. To be more "real-to-life" you should have the targets fade as the sweep moves away and update the position of the "target" only when the sweep corresponds to it's updated position.
Also - there is an equivalent to the PPI for height called an RHI (range height indicator) in which case the sweep moves up and down in a rectangular field showing the elevation and range of the target.
Smile Yeah well - I was a radar tech in a previous life - what can I say...
GeneralRe: Terminology
JimBlaney
10:49 21 Aug '07  
In response to your feedback (challenges), my next step will be to implement the "true radar" way of entity discovery. In addition, I will add the on-sweep-only update and fade the items after time (based on the rotation speed of the sweep). This should be fun to figure out, and I hope to have this updated before my fall classes begin! Feel free to add any relevant examples of "proper" functionality as further comments, as I am only dreaming this up as I go along.

Thanks for all the ideas!

JimBlaney
GeneralRe: Terminology
rapid2k2
13:34 21 Aug '07  
It is funny to implement it, but nowadays radar systems format its information in a standard format (ASTERIX, for example) that is transmited using a LAN/WAN to processing systems. These systems integrate several sources of information and present only one plot per plane. The idea behind this is to be able to transport radar information to several places (control positions, terminal areas etc) without the need to send raw/analog video.

Just my 2 cents of € Smile
GeneralRe: Terminology
farhatmasood
23:49 12 Mar '10  
How will you generate sweep function? As in the targets should appear for a certain time and fade away...
Is there any way to predict the future location of the item on PPI display?
Regards
Farhat.
GeneralNeat!
Sean Michael Murphy
8:58 17 Aug '07  
If you want to make it really authentic, you should only update the position of the RadarItem you are tracking when the sweep passes over it.

Interesting UI gadget though.

Thanks.
Sean
GeneralMinor Glitch
JimBlaney
7:11 17 Aug '07  
I've also uncovered a minor glitch -- if you let the demo app run for some time, you'll notice that the drawing of the ScanLine slows down gradually. I will continue to investigate.

JimBlaney
GeneralRe: Minor Glitch
aglt
6:42 24 Aug '07  
It is a minor overlook but it has major effect on the processing power.. It seems he forgot to set the boolean flag in the Radar.AddItem method.

The main form has a timer that adds items to the Radar infinitely because the flag in the Radar.AddItem is alwais set to true, and the Radar.Draw method will draw every item in the (infinitly growing) list each time. That is why the program gets slower..


public void AddItem(RadarItem item)
{
bool bFlag = true;//this is the flag that will alwais be true
for (int i = 0; i < radarItemList.Count; i++)
{
if (radarItemList[i].ID == item.ID)
radarItemList[i] = item;// Maybe here it should be set to FALSE
}

if (bFlag)//here it will add itmes each time the timer ticks - infinitly
radarItemList.Add(item);

Draw();
}

void Draw()
{
//... draws every item in the list and it gets bigger by the second
foreach (RadarItem item in radarItemList)
{
item.DrawItem(this, g);
}


This will work


public void AddItem(RadarItem item)
{
for (int i = 0; i < radarItemList.Count; i++)
{
if (radarItemList[i].ID == item.ID)
{
return;
}
}
radarItemList.Add(item);
Draw();
}


GeneralRe: Minor Glitch
JimBlaney
6:28 30 Aug '07  
Here's the solution that I ended up implementing...

public void AddItem(RadarItem item)
{
bool bFlag = true;
for (int i = 0; i < radarItemList.Count; i++)
{
if (radarItemList[i].ID == item.ID)
{
radarItemList[i] = item;
bFlag = false;
break;
}
}
if (bFlag)
radarItemList.Add(item);
Draw();
}


JimBlaney
GeneralDerive Radar from a control based class [modified]
rvpilot
5:41 17 Aug '07  
Why not derive your Rader class from UserControl or Panel and put the rendering code in the OnPaint handler. That way the Radar becomes an item tha you can add to the toolbox and place on a form/panel by drag/drop from the ToolBox.

I suspect you have followed the VB6 way of doing things in that you draw to the deveice handle of a pictureBox. In c# you can go one step further than that and have a self contained control which makes your implementation in the Form really simple. i.e.

Create the object and add/remove items from it. All the painting and sizing would then be done in the Radar class. Have a look on the CodeProject for user controls and you'll see how this can be achieved in C#.

Your radaritems can also be derived from a baseradaritem class which can contain the common properties of all the items, i.e. azimuth, etc.

Other than that its a very nice looking control Wink


-- modified at 10:48 Friday 17th August, 2007
GeneralRe: Derive Radar from a control based class
JimBlaney
7:09 17 Aug '07  
I originally did an implementation of Radar : UserControl.

I'm can't remember exactly why I redid it, other than a learning experience? I think there was a niche implementation I was working on that required... something...

Thanks for the feedback!

JimBlaney
GeneralRe: Derive Radar from a control based class
aglt
14:45 25 Aug '07  
rvpilot wrote:
Why not derive your Rader class from UserControl or Panel and put the rendering code in the OnPaint handler.

Well the Radar class is basicly a renderer. You could easily make a UserControl that has the Radar object as a member and make it draw the Radar in the OnPaint event ...


Last Updated 17 Aug 2007 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010