Click here to Skip to main content
15,867,568 members
Articles / Multimedia / GDI+

Marching Ants

Rate me:
Please Sign up or sign in to vote.
4.93/5 (21 votes)
23 Jul 2008CPOL3 min read 64.8K   907   50   19
Learn how to create marching ants easily and efficiently

Image 1

Introduction

Marching ants are a common phenomenon in graphics programs that use them to show an area that has been selected by the user. Usually, this area can be a union of various shapes and even user-selected areas. This article will attempt to show you how to create your own marching ants program.

Background

It is preferable that you know the basics of GDI+. I will attempt to show everything that you need to know to create a working program, however.

Setting Up the Selected Area

The most important part of the technique is a pair of objects: a GraphicsPath object and a Region object. Region is found in System.Drawing, and GraphicsPath is found in System.Drawing.Drawing2D. Although it is not necessary, I created a separate class where I stored my GraphicsPath and Region.

The meat of the code is right here:

C#
public void AddRectangle(Rectangle rectangle)
{
    _gp.AddRectangle(rectangle);
    _region.Union(_gp);
}

public void AddCircle(Rectangle rectangle)
{
    _gp.AddEllipse(rectangle);
    _region.Union(_gp);
}

public void AddFreeform(Point[] points)
{
    _gp.AddPolygon(points);
    _region.Union(_gp);
}

After initializing my GraphicsPath (_gp) and Region (_region), I have several methods for adding new shapes to them. The Region is necessary because it is the only class that can do a union of these various shapes.

Creating the Ants

The only other part of my code is the rendering code. To create the marching ants effect, I use a sneaky little trick. Normally, the GraphicsPath cannot do a union, so you would have lines from several different rectangles (instead of just the outside lines). I create a Bitmap and then fill in the center of the lines with the Region, which gets rid of all of the unnecessary lines. Then, I set the color I just filled in to be the transparent color for the Bitmap and draw it on my surface.

C#
private void Canvas_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawImage(_image, new Rectangle(0, 0, 
                         _image.Width, _image.Height));
    //draws your image

    e.Graphics.FillRegion(new SolidBrush(Color.FromArgb(128, 0, 0, 255)), 
                          _region);
    //fills the selected region with 
    //a semi-transparent blue for a nice effect

    Pen pen = new Pen(Color.White, 1);
    pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
    pen.DashPattern = new float[2] { 3, 3 };
    //these lines set up a pen that will draw dashed white lines

    Bitmap ant = new Bitmap(CanvasPanel.Width, CanvasPanel.Height);
    Graphics g = Graphics.FromImage(ant);
    //creates a Graphics object from the Bitmap we will draw the ants on

    g.Clear(Color.Magenta);
    //makes the Bitmap Magenta so that the outsides will be transparent

    g.DrawPath(new Pen(Color.Black), _graphicsPath);
    g.DrawPath(pen, _graphicsPath);
    //draws a black outline (for underneath) 
    //and the dashed white line on top

    g.FillRegion(new SolidBrush(Color.Magenta), _region);
    //fills in the middle so the extra lines don't show

    ant.MakeTransparent(Color.Magenta);
    //makes the areas not covered by the marching ants transparent

    e.Graphics.DrawImageUnscaled(ant, 0, 0);
    //draw the ants on to the image
}

Fixing the Center

Because the GraphicsPath and the Region are the same size, drawing the Region inside the GraphicsPath actually obscures some of the ants. To fix this, we can use a handy function of the GraphicsPath class - Widen. I have found that it looks best to widen 1 or 2 pixels. Here is a function that I used to fix this:

C#
public GraphicsPath Line()
{
    GraphicsPath gp = new GraphicsPath();
    if (_gp.PointCount > 0)                
    {        
        //I had to add this if statement so the program 
        //wouldn't crash if my GraphicsPath was still empty
        gp.AddPath(_graphicsPath, false);
        gp.Widen(new Pen(Color.White, 2));
    }
    return gp;
}

I used this function so that I wouldn't widen my original GraphicsPath object every frame or every time I added a new shape (this is an easy-to-make error that can quickly crash your program).

Animating the Ants

To animate the ants, I merely created a Timer and redrew the image at each tickCount. I am sure that there are more efficient ways to do this (such as invalidating the correct region), but for now this is simpler.

C#
private void AntTimer_Tick(object sender, EventArgs e)
{
    _antOffset++;
    if (_antOffset > 50) _antOffset = 0;
    Canvas.Refresh();
}

Then, up in the OnPaint section of the code, you need to add a line that takes this offset into effect:

C#
pen.DashOffset = _antOffset;

Placing this code with the other code that sets the properties for your pen should give you a fully working marching ants program.

Points of Interest

Many thanks to the authors of The Secret of Marching Ants and Marching Ants Revisited. Their programs gave me some great ideas, although I think that my program is more efficient and allows for more complex paths.

Other

This is my first article, please give me feedback. :-)

History

  • 7/14/2008 - Original upload
  • 7/23/2008 - Source updated

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Unknown
I have been coding the last several years for fun. I taught myself c# and have been enjoying it ever since.

Comments and Discussions

 
QuestionBrilliant Solution Pin
Jim Acer2-Apr-21 4:42
Jim Acer2-Apr-21 4:42 
GeneralMy vote of 5 Pin
Maxwolf Goodliffe13-Dec-14 23:48
Maxwolf Goodliffe13-Dec-14 23:48 
QuestionMy vote of 5 Pin
KnolleManneke13-Feb-13 8:52
KnolleManneke13-Feb-13 8:52 
QuestionC++ implementation Pin
pintu_kuldip773319-Jan-12 22:05
pintu_kuldip773319-Jan-12 22:05 
GeneralMy vote of 5 Pin
pmorelfourrier1-Oct-11 10:54
pmorelfourrier1-Oct-11 10:54 
General_graphicsPath Pin
agriweb21-Sep-09 10:56
agriweb21-Sep-09 10:56 
GeneralRe: _graphicsPath Pin
Jim Acer2-Apr-21 4:41
Jim Acer2-Apr-21 4:41 
QuestionImage Transition and other issues Pin
Member 380027024-Apr-09 1:43
Member 380027024-Apr-09 1:43 
Hi,

Great Article.
I have a question please,
I would like to adjust the selected region according to the transition in that area in images.
Any idea on how to do it?

Also,

Could you please proide examples for using the application for drawing free hand shapes?

Thanks.

Gil
GeneralSource Code Pin
bfd31-Jul-08 6:08
bfd31-Jul-08 6:08 
GeneralVery Nice Pin
Paul Conrad26-Jul-08 16:39
professionalPaul Conrad26-Jul-08 16:39 
GeneralSource Code Pin
Hax0r77815-Jul-08 5:22
Hax0r77815-Jul-08 5:22 
GeneralRe: Source Code Pin
sam.hill15-Jul-08 19:06
sam.hill15-Jul-08 19:06 
GeneralRe: Source Code Pin
strictly8616-Jul-08 0:27
strictly8616-Jul-08 0:27 
GeneralRe: Source Code Pin
Hax0r77822-Jul-08 19:59
Hax0r77822-Jul-08 19:59 
GeneralRe: Source Code Pin
Teashirt225-Jul-08 7:38
Teashirt225-Jul-08 7:38 
Generalgood Pin
Aamir Mustafa14-Jul-08 7:26
Aamir Mustafa14-Jul-08 7:26 
QuestionWhere is the source code? Pin
TBermudez14-Jul-08 4:25
TBermudez14-Jul-08 4:25 
GeneralGood job Pin
strictly8613-Jul-08 22:39
strictly8613-Jul-08 22:39 
GeneralAwesome Pin
JRSofty13-Jul-08 21:51
professionalJRSofty13-Jul-08 21:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.