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

Sample Image - image001.jpg

Introduction

I decided to document my little 3D pie chart demonstration and possibly submit it to CodeProject. I must note I have done very little with graphical programming.

It all started when I was contemplating the length of a rounded edge of a pie slice given the radius and the degree of the slice angle. I never did find the formula, but I figure you could take the circumference of the circle as a whole then divide it by eight pieces if the degree was 45 as in the chart above. Hold on, that is the answer!

Anyway, I then started to ask myself how you can programmatically draw a pie chart. That might give my some idea. I found a complex WebChart control off CodeProject by user blong. I also had some simple ASHX code from Jeff Prosise on MSDN, Aug. 2002.

The Graphics method FillPie can draw a pie slice given the mid point, the length and width of the ellipse, starting angle and sweep angle. The mid point is the graphical coordinates where the "device context" will put the middle of the ellipse. Think of it as 0, 0 in an x, y coordinate system where the degrees are as in Figure 2.

I created a VB.NET project to demo the FillPie method, a DrawPieChart example, and a Draw3DPieChart demonstration where this ASP.NET (ASPX page) demo came from. Unfortunately, I don�t have an IIS server accessible to the Internet, but the Windows application can be downloaded here.

The sweep angle is self explanatory, but it threw me off at first. If the start angle was 35 degrees and you wanted a pie slice to go to 90 digress, you would set the sweep to 55 not 90.

To draw the simple pie chart I just created a loop to start at 0 and go to 315 skipping every 45 degrees. Note: I randomly chose brush colors and I didn�t think that 360 being the same as 0 would be a problem until I did the 3D demo.

The 3D test came next. For pie slices less then 180 degrees required that I used a System.Drawing.Drawing2D.HatchBrush with the random color selected for the slice, and drew 10 slices dropping the y coordinate on each FillPie method call to give the illusion of depth.

To draw the displaced pie slice was an added challenge. I forget what the code did without the displaced slice, but to draw the chart in Figure 1, I noted that starting with the pie slice at 180 degrees and wrapping around (0 to 315, see code below), would draw the chart correctly. For simplicity sake, I "painstakingly" kept the degrees under 360.

There it is; pretty simple. I figure if it was not worth the time to design a better, reusable version of the project. What would be the best format? This ASPX as listed below? Use an ASHX file like Jeff�s? What about the legend, chart title? It would take more time and desire then my simple inquiry. Besides, you might as well use the WebChart control stated above. It�s already written!

Assuming I�d take the time to write a reusable chart, here are the steps I�d use for the algorithm. Sort the array or list of elements (test scores, votes. etc.) from greatest number to the smallest. In this demo all degree angles for the slices are 45.

To determine angle degrees per slice I would sum up the elements, take the value of an element divide it by the sum, and then multiply it by 360. Take the simple arbitrary sample data of .NET platform users:

  1. J# Users : 5%
  2. C# Users : 80%
  3. VB.NET Users : 15%

Sorting would result in {80, 15, 5} and starting at 180 degrees, loop through the list. The "C# Users" slice would sweep (80/100*360) or 288 degrees; "VB.NET Users", 54 degrees; and the displaced "J# Users" slice, 18 degrees.

In my demo, I just randomly select colors using RGB values. Known solid colors would make it more desirable to the eye. Another pleasing feature was this:

objGraphics.SmoothingMode = SmoothingMode.AntiAlias;

Compare this to the choppy images created without this line of code. I think that�s it. Hope it is worth something to someone. Maybe this documentation is just for my own purposes when I look at the code years from now.

The chart wouldn�t print straight from Internet Explorer. I wonder if that was because I wasn�t referring (href) the page from an HTML image tag - which did print.

    <%@ Import Namespace="System.Drawing"%>
    <%@ Import Namespace="System.Drawing.Imaging"%>
    <%@ Import Namespace="System.Drawing.Drawing2D" %>
    <script language="C#" runat="server">

    void Page_Load(Object sender, EventArgs e)
    {
        // Since we are outputting a Jpeg, set the ContentType appropriately

        Response.ContentType = "image/jpeg";

        // Create a Bitmap instance that's 468x60, and a

        Graphics instance

        const int width = 300, height = 300;

        Bitmap objBitmap = new Bitmap(width, height);
        Graphics objGraphics = Graphics.FromImage(objBitmap);

        // Create a black background for the border

        objGraphics.FillRectangle(new SolidBrush(Color.White), 0, 0,
width, height); Draw3DPieChart(ref objGraphics); // Save the image to a file objBitmap.Save(Response.OutputStream, ImageFormat.Jpeg); // clean up... objGraphics.Dispose(); objBitmap.Dispose(); } // Draws a 3D pie chart where ever slice is 45 degrees in value void Draw3DPieChart(ref Graphics objGraphics) { int iLoop, iLoop2; // Create location and size of ellipse. int x = 50; int y = 20; int width = 200; int height = 100; // Create start and sweep angles. int startAngle = 0; int sweepAngle = 45; SolidBrush oibjBrush = new SolidBrush(Color.Aqua); Random rand = new Random(); objGraphics.SmoothingMode = SmoothingMode.AntiAlias; //Loop through 180 back around to 135 degress so it gets drawn
// correctly.
for( iLoop = 0; iLoop <= 315; iLoop += 45) { startAngle = (iLoop + 180) % 360; objBrush.Color = Color.FromArgb(rand.Next(255), rand.Next(255),
rand.Next(255)); // On degrees from 0 to 180 draw 10 Hatched brush slices to show
// depth
if((startAngle < 135) || (startAngle == 180)) { for(iLoop2 = 0; iLoop2 < 10; iLoop2++) objGraphics.FillPie(new HatchBrush(HatchStyle.Percent50, objBrush.Color), x, y + iLoop2, width, height, startAngle, sweepAngle); } // Displace this pie slice from pie. if(startAngle == 135) { // Show Depth for(iLoop2 = 0; iLoop2 < 10; iLoop2++) objGraphics.FillPie(new HatchBrush(HatchStyle.Percent50, objBrush.Color), x - 30, y + iLoop2 + 15, width, height, startAngle,
sweepAngle); objGraphics.FillPie(objBrush, x - 30, y + 15, width, height, startAngle, sweepAngle); } else // Draw normally objGraphics.FillPie(objBrush, x, y, width, height, startAngle, sweepAngle); } } </script>
You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralHow to See Chart ??
Ozgur KOC
5:17 29 Dec '07  
How to See Chart ??
I cant see the chart.
<img src="chart.aspx"> however it doesnt seen.
Please Help</img>
GeneralRe: How to See Chart ??
Rajib Ahmed
6:09 3 Mar '08  
it probably isn't pointing correctly. Use the image control, and just set change the ImageUrl tp "~/Chart.aspx"

Rajib Ahmed

GeneralHow to link it to the Database
Sijo Mathew
2:45 11 Oct '07  


How to Create a 3D chart
Data From SQL server

sdsdfsd

QuestionBroken link yet again
darksander
5:14 19 Sep '07  
Hi!
I was looking for some pie charts examples for ASP.NET, and run into this article.. Unfortunately none of the links are available anymore Sigh .
I can see this is a pretty old article, but is there a chance for me to have a look at the source code?
Thanks Big Grin

no kiddin'

GeneralFormula you were searching for
Anthony Potts
7:01 26 May '06  
First of all, awesome. I was looking for something like this.

I know it's been a while, and you probably don't care to know the answer to the original question *but*, here's a very short course (from a mathematician turned programmer):

"The length of a rounded edge of a pie slice given radius and degree" is called it's arc length. (If you google this term you'll get lots of stuff.) An angle, A, in radians, is equal to the ratio of the arc length, s, by the radius, r. So, we could rewrite this relationship A*r=s, but that's if you know the angle in radians. If the angle is in degrees, this formula is instead, A*r*180/pi = s.

Anyway, thanks for sharing.

"If you really want something in this life, you have to work for it. Now, quiet! They're about to announce the lottery numbers..."
- Homer Simpson

GeneralTypo
paulanthony
23:07 13 Feb '06  
SolidBrush oibjBrush

should be

SolidBrush objBrush


General3D Pie Edit Version with subtitle
hockey2
23:00 23 May '05  
private string[] productCount = new string[13];
private string[] productName = new string[8];
private string[] productPercent = new string[8];
private float[] Angle = new float[8];

private void Page_Load(object sender, System.EventArgs e)
{
strNowYear = (string)Request["year"];

if(strNowYear == null)
strNowYear = DateTime.Today.Year.ToString();

GetList3();
DrawGraphic3();
}

private void GetList3()
{
try
{
DataSet objDs = new Statistisc().SelectSaleRate(strNowYear);

for(int i=0;i<8;i++)
{
productCount[i] = objDs.Tables[0].Rows[i][2].ToString();
productPercent[i] = objDs.Tables[0].Rows[i][3].ToString();

if(Convert.ToInt32(productPercent[i]) != 0)
Angle[i] = (float)(Convert.ToInt32(productPercent[i]) * 3.6);

productName[i] = objDs.Tables[0].Rows[i][1].ToString();
}
}
catch(Exception ex)
{
Response.Write("<script>alert('Exception : " + ex.Message.Replace("'","") + "');</script>");
}
}


private void DrawGraphic3()
{
Response.ContentType = "image/Gif";
const int width = 700, height = 200;

Bitmap objBitmap = new Bitmap(width, height);
Graphics objGraphics = Graphics.FromImage(objBitmap);

// Create a black background for the border
objGraphics.FillRectangle(new SolidBrush(Color.White), 0, 0,
width, height);

Draw3DPieChart(ref objGraphics);

// Save the image to a file
objBitmap.Save(Response.OutputStream, ImageFormat.Gif);

// clean up...
objGraphics.Dispose();
objBitmap.Dispose();
}

// Draws a 3D pie chart where ever slice is 45 degrees in value
void Draw3DPieChart(ref Graphics objGraphics)
{
// Create location and size of ellipse.
int x = 60;
int y = 20;
int width = 200;
int height = 100;


// Create start.
float startAngle = 0;

SolidBrush objBrush = new SolidBrush(Color.Aqua);

objGraphics.SmoothingMode = SmoothingMode.AntiAlias;

Color[] color_rgb = {Color.FromArgb(255,0,0), Color.FromArgb(255,255,0),
Color.FromArgb(100,100,100), Color.FromArgb(0,255,0),
Color.FromArgb(0,255,192), Color.FromArgb(192,192,0),
Color.FromArgb(100,0,192), Color.FromArgb(0,0,255)};

for(int iLoop=0; iLoop<15; iLoop++)
{
startAngle=0;
for(int i=0; i<8; i++)
{
objBrush.Color = color_rgb[i];
if(iLoop==14)
objGraphics.FillPie(objBrush, x,
y - iLoop + 25, width, height, startAngle, Angle[i]);
else
objGraphics.FillPie(new HatchBrush(HatchStyle.Percent50,
color_rgb[i]), x,
y - iLoop + 25, width, height, startAngle, Angle[i]);
startAngle += Angle[i];
}
}

for(int i=0; i<8; i++)
{
objBrush.Color = color_rgb[i];

objGraphics.FillRectangle(objBrush, x + width + 80, y + i*18, 14, 14);
objGraphics.DrawString(productName[i],new Font("Courier New",11),new SolidBrush(Color.FromArgb(0,0,0)),
x + width + 100, y + i*18);
objGraphics.DrawString(productPercent[i] + "%",new Font("Courier New",11),new SolidBrush(Color.FromArgb(0,0,0)),
x + width + 250, y + i*18);

objGraphics.DrawString(productCount[i],new Font("Courier New",10),new SolidBrush(Color.FromArgb(0,0,0)),
x + width + 310, y + i*18);
}

}
}
GeneralRe: 3D Pie Edit Version with subtitle
Belkira
0:27 3 May '06  
What's this object ?

DataSet objDs = new Statistisc().SelectSaleRate(strNowYear);

Statistisc should be a class you developp ?D'Oh!
GeneralQuality?
Nir Levy
4:08 20 Dec '04  
First, very nice piece of code.

Question: The image quality of the resulting chart is somewhat poor. I tried changing the output format from JPG to GIF but still the result is somewhat pixelized. Anyone know why and how this can be fixed?

best regards
/NL

polynr69 at gmail dot com
GeneralRe: Quality?
shahab farooqui
18:04 15 Oct '05  
Try outputting it to png format:
Vb.net code
===========
Dim MemStream As New MemoryStream

Dim objBitmap As Bitmap = New Bitmap(width, height)
Dim objGraphics As Graphics = Graphics.FromImage(objBitmap)

' Create a black background for the border
objGraphics.FillRectangle(New SolidBrush(Color.White), 0, 0, width, height)

Draw3DPieChart(objGraphics)

' send the image to the memory stream then output
objBitmap.Save(MemStream, ImageFormat.Png)
'output the me stream
MemStream.WriteTo(Response.OutputStream)
' clean up...
objGraphics.Dispose()
objBitmap.Dispose()

C# code

GeneralHow to add labels to this pie chart sectors
sriamjunk
23:54 31 Oct '04  
Hi MJDamron and othere contributors to this site, could some one help me out in getting labels to this pie chart. It would be great if i could get a label for each of the sectors in the pie Smile


s rajesh
GeneralHow To Put Label Behind Per Pie Slices
bambooElbimbo
16:02 9 Jul '04  
To Mr B. Long and Other Experts,

Just asking if it is possible to put labels behind pie slices as same as the Show Legend output in your WebChart?
This is to easily view the values in their perspective slices.
I hope you can make it very well and ASAP.....

Wink I admired your code..very useful and interesting.. Cool

Thank You very much....!!!

bamboo el bimbo


bamboo el bimbo
GeneralHow To Put Label Behind Per Pie Slices
bambooElbimbo
15:50 9 Jul '04  
To Mr B. Long and Other Experts,

Just asking if it is possible to put labels behind pie slices as same as the Show Legend output in your WebChart?

Thank You very much....!!!

bamboo el bimbo
General3D Pie Chart in ASP.NET
Anonymous
3:31 25 May '04  
3D Pie Chart in ASP.NET sux...
Nice trick to remove that last part from the pie...Sigh Sigh
GeneralBug? Not your code
MrEyes
6:59 2 Dec '03  
Let me start by saying that this is an excellent article, as somebody who is fairly new to gdi who was tasked with generating pie charts this is an excellent resource.

Now it seems there is a "feature" in the MS FillPie code the reason being is that the pie sectors are painted incorrectly.

If you generate a 2D pie chart with 8 45 degree sectors, this paints exactly as you would imagine. But if you reduce the height to give the illusion of 3D the sectors are drawn incorrectly.

You can see this "feature" in action on the screenshot you posted above, starting from midday and moving clockwise, the first two sectors should be the same size, but they look different which gives the impression that the two sectors represent different amounts.

I havent come up with a solution to this yet, but I am thinking that it may be possible to generate the image and then squash it to maintain the 3D illusion.

post.mode = signature;
SELECT everything FROM everywhere WHERE something = something_else;
> 1 Row Returned
> 42
Generalquestion
newmem
12:04 2 Oct '03  
Excellent code & documentation.
I converted the 3D pie chart code to vb to use in my asp.net web application. But for some reason, I can not get the "displaced pie slice" to be draw. Finally when the loop was changed from 315 to 360 , the pie slice was drawn but -
1) it was not displaced from the chart
2) the slice was drawn as single dimensional

any clue what's going on? Cry

newmem
GeneralTruncated image display?
msisson
7:44 15 Sep '03  
First of all my congratulations and thanks for an AWESOME code sample. I'm having two small problems though that maybe someone might be able to help me with.

Q1. I have a page that is constantly reposting and refreshing it's view. Your pie chart is showing on each page with refreshed data. Sometime the graphic seems to get cut down the middle. I know it's a browser display problem because if I save the image to the desktop the image itself looks fine. Is there something I could do via Javascript or in ASP.NET to make sure that the image display completely each time?

Q2. Is there a quick fix to make sure that the resulting graphic is only as big as it needs to be? For my purposed I'm only displaying the pie without legends or titles. It would be great if the graphic is only as big as the pie.


Thanks again for a great sample!


GeneralBroken link
Anonymous
12:36 18 Aug '03  
Sorry about that. I moved some stuff around on my server.

http://www.digitalworx.net/~mjdamron/misc/Code/DrawPie/DrawPie.zip
GeneralIs there any way to add image to a listbox?
dathq
15:49 8 Aug '03  
I want to add some image to a listbox but...Confused ! Can you help me?

dathq
GeneralRe: Is there any way to add image to a listbox?
seewood
20:43 29 Feb '04  
sorry, but u cann't
u can put the image to a layout which look like a listbox
GeneralRe: Is there any way to add image to a listbox?
MJDamron
6:22 13 Jan '06  
Yes, see this:

http://digitalworx.net/~mjdamron/misc/Code/Controls/[^]

Use OwnerDraw.

Sorry about the late reply. Smile



Michael Damron
mjdamron@digitalworx.net
GeneralCode Typo: oibjBrush
ronemtz
5:48 7 May '03  
SolidBrush oibjBrush = new SolidBrush(Color.Aqua);



Ron M.
GeneralNotice
MJDamron
5:59 2 May '03  
Thanks to Bryan Long for insight on drawing functionality.

I don't recall using anything from Jeff, but for liability purposes: Thanks.;P

Michael Damron
mjdamron@digitalworx.net
GeneralRe: Notice
PVK
10:48 8 May '03  
How to go about Bar charts??
Need help.Confused

Thanks
vinay
GeneralRe: Notice
MJDamron
15:35 10 May '03  
Using the Graphics.FillPolygon method with the HatchBrush as in the above, you can do a 3D bar graph.

I am thinking about writing a demo to submit.

Basically, draw a series of rhombus shapes starting at the base and up the y-axis ending with the solid brush rhombus shape at the top.

== Follow up ==

Well, I created a demo on my old laptop while cooped up in my room. The article and the code samples can be downloaded from:

http://www.digitalworx.net/~mjdamron/code/Graphics/

The image in the Word document is really nasty. Run the exe on your machine for a beter image.

Also, I was just reading the MSDN magazine as I often do (when I remember) and found Dino's 2D bar chart web control.

See http://msdn.microsoft.com/msdnmag/issues/03/06/CuttingEdge/default.aspx

Michael Damron
mjdamron@digitalworx.net


Last Updated 28 Apr 2003 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010