Introduction

During the development of a videogame skeleton, one of my biggest concerns was the drawing of a large interstellar map. Since it was just a skeleton, implementing 3D graphics with OpenGL or Direct3D was not an option. I soon discovered that GDI+ could very well fit to my needs. Next I had to face mainly two issues:

While .NET panels reason in terms of "pixels", my map was based on some "light years" metrical units.

I had to imagine an algorithm to easily paint a sphere (or spheroid) on that map

The included code shows how I solved those problems. It could be helpful to show how easy is to add graphics and shapes using GDI+ and .NET.

Conversion between pixel geometry and logical-units geometry

When we want to display something using GDI+, we must reason in terms of pixels. The Graphics object can be obtained by calling the CreateGraphics method from any inherited WinForm control. So, for instance, a Panel is an optimal choice as a drawing surface, much better than the form itself. When a Graphics object is initialized, it's geometry is based on the pixel displayed, being (0,0) the left-upper corner of it.

If I must draw a line, say, from the point (10,10) to the point (30,30) I must call:

Since every method and property of GDI+ is based on pixels, drawing items in terms of some other units of measure implies a conversion. Also, when we use "real world" formulae, they must be adapted to the "pixel" logic. Instead of spreading the conversions throughout the code, a class is what is needed.

We could use the .NET library class Graphics.PageScale to do so, since there are overloaded Graphics methods that accept float numbers (measure units) as input instead of integer numbers (pixel). But I preferred to write a class that has the same functions of PageScale, but it's slightly different in concept. You do not have to compute the PageScale constant, since it does that for you. Plus, you may use double precision.

The GridView class provides the methods to pass from a "pixel" geometry to some other "logical units" geometry. So, when you have to draw a rectangle with a width of 4.5 cm and a height of 3.0 cm to a 400x500 panel, all you have to do is:

Initialize GridView with desired width of panel in logical units (if you want to display the 4.5 wide rectangle, a logicalW parameter of 10.0 seems perfect)

The algorithm for drawing the sphere is very simple, and it is based on drawing arcs in a rectangle whose dimensions shrink. The algorithm draws the arcs first from right to left, then from top to bottom.

Modifying the number of loops (j-=10) you can obtain finer wires. You can also modify the width of the Pen in order to get different results.

Point of Interest

When you draw something on a Control, on a Panel in this case, if you cover the control with another control (or another window), the contents just drawn disappears. For this reason, every new sphere that you draw is collected into an ArrayList collection. Whenever the Paint event is raised, I call the paint method for every shape in the collection.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.