CSDN专家博客精华版

为人民服务!
  首页  :: 新随笔  :: 管理

.net实现3D饼图(源码1)

Posted on 2007-12-17 10:18  csdnexpert  阅读(262)  评论(0编辑  收藏  举报

点击此处下载源码+test代码(99KB,rar)

本来想改改几个bug再整理下发上来的。但是最近工作比较紧张,没有时间。发出来大家看看。多提提意见。帮忙改改。 

using System;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;


namespace qchart
{
    
/// <summary>
    
/// chart 的摘要说明。
    
/// 抽象类,所有chart的父类
    
/// </summary>

    public abstract class Chart
    
{
        
        
public int width,height;
        
public int count = -1;
        
public ArrayList al =  null;
        
public Bitmap bitmap = null;

        
public Chart()
        
{
            init(
400300);
        }


        
public Chart(int w,int h)
        
{
            init(w, h);
        }


        
private void init(int w, int h)
        
{
            width 
= w;
            height 
= h;
        }



        
public void saveBitmap(string file)
        
{
            bitmap.Save(file, ImageFormat.Jpeg);
        }


        
public void saveBitmap(Stream stream)
        
{

            bitmap.Save(stream, ImageFormat.Jpeg);
        }


        
public abstract void createBitmap();

    }

}

 

 


 

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections;
using System.IO;

namespace qchart
{
    
/// <summary>
    
/// 饼图的抽象类,所有样式的饼图继承此类
    
/// </summary>

    public abstract class PieChart : Chart
    
{
        
public int startAngle = 0;

        
public PieChart()
        
{
            init(
400300);
        }

        
public PieChart(int w,int h)
        
{
            init(w, h);
        }


        
private void init(int w, int h)
        
{
            width 
= w;
            height 
= h;
            al 
= new ArrayList();
        }


    

        
public void addPieData(int val,string name)
        
{
            PieData pd 
= new PieData(val,name);
            al.Add(pd);
            count
++;
        }


        
public void addPieData(int[] vals,string[] names)
        
{
            
int l = vals.Length<names.Length?vals.Length:names.Length;
            
for(int i=0;i<l;i++)
            
{
                addPieData(vals[i],names[i]);
            }

            
//count += l ;
        }


        
public void removePieData(int index)
        
{
            
if(index >= 0 && index <=count)
            
{
                al.RemoveAt(index);
                count
--;
            }

        }




    }

}

 

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections;
using System.IO;

namespace qchart
{
    
/// <summary>
    
/// 
    
/// </summary>

    public  class PieChart2D : PieChart
    
{

        
public PieChart2D() : base()
        
{
           
        }

        
public PieChart2D(int w, int h)  : base(w, h)
        
{

        }



        
public override void createBitmap()
        
{
            
//用指定的大小和格式初始化 Bitmap 类的新实例
            bitmap = new Bitmap(width, height);
            
//创建绘图对象
            Graphics g = Graphics.FromImage(bitmap);
            
//清除整个绘图面并以透明背景色填充
            
//g.Clear(Color.Transparent);
            g.Clear(Color.Snow);

            Rectangle r 
= new Rectangle(00, width, height);

            
//int[] angle = {30,60,90,45,135} ;
            int sum = startAngle;

            Pen p 
= new Pen(Color.YellowGreen);

            
for (int i = 0; i <= count; i++)
            
{
                PieData pd 
= (PieData)al[i];
                
float f = Convert.ToSingle(pd.val);
                g.FillPie(Qcommon.b[i 
% 12], r, sum, f);
                g.DrawPie(p, r, sum, f);
                sum 
+= Convert.ToInt32(f);
            }


        }





    }

}

 

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections;
using System.IO;
using System.Drawing.Drawing2D;

namespace qchart
{
    
/// <summary>
    
/// 
    
/// </summary>

    public  class PieChart3D : PieChart
    
{
        
static readonly int deta = 30;
        
//static readonly int dpt  = 5;

        
public PieChart3D() : base()
        
{
           
        }

        
public PieChart3D(int w, int h):base(w,h)
        
{
            
        }



        
public override void createBitmap()
        
{
            
//bool flag = false;

            
//用指定的大小和格式初始化 Bitmap 类的新实例
            bitmap = new Bitmap(width , height );
            
//创建绘图对象
            Graphics g = Graphics.FromImage(bitmap);
            
//清除整个绘图面并以透明背景色填充
            
//g.Clear(Color.Transparent);
            g.Clear(Color.Snow);

            Rectangle rs 
= new Rectangle((width - 400/ 2 - 50, (height - 300/ 2 + deta/2400300);

            
//g.FillPie(Qcommon.b[0], rs, 0, 180);

            Rectangle r  
= new Rectangle((width - 400/ 2 - 50 , (height - 300)/2 - deta/2400300);
            
//Rectangle rc = new Rectangle((width - 400) / 2 + 50, (height - 300) / 2, 300, 300);

            
int sum = startAngle % 360;

            Pen p 
= new Pen(Color.YellowGreen);
            Pen ps 
= new Pen(Color.DarkGray);

            Point pt 
= new Point();
            
double a = r.Width / 2d;
            
double b = r.Height / 2d;
            pt.X 
= r.X + r.Width / 2;
            pt.Y 
= r.Y + r.Height / 2;

            
//画底面和侧边
            for (int i = 0; i <= count; i++)
            
{
                
double af = sum / 180d * Math.PI;
                
int sign = Math.Sign(Math.Cos(af));
                
double k = Math.Tan(af);

                
double dx = sign * Math.Sqrt(1 / (1 / (a * a) + k * k / (b * b)));
                
double dy = k * dx;

                
int x = pt.X + (int)dx;
                
int y = pt.Y + (int)dy;


                PieData pd 
= (PieData)al[i];
                
float f = Convert.ToSingle(pd.val);

                
int nextsum = (sum + Convert.ToInt32(f)) % 360;

                g.FillPie(Qcommon.b[i 
% 12], rs, sum, f);


                
if (sum > 180)
                
{
                    
if (nextsum < 180)
                    
{
                        g.FillPolygon(Qcommon.b[i 
% 12], new Point[] new Point(pt.X + (int)a, pt.Y), new Point(pt.X + (int)a, pt.Y + deta), pt });
                        g.DrawLine(p, 
new Point(pt.X + (int)a, pt.Y), new Point(pt.X + (int)a, pt.Y + deta));

                        
//pt = subsidy(g, sum, p, pt, a, b, i + 1, x, y, nextsum);

                        Point pend 
= findPoint(nextsum, a, b, pt);
                        
if (nextsum < 90)
                        
{
                            printSmailRect(g, i, pend);
                            g.DrawLine(p, 
new Point(pend.X, pend.Y + deta), new Point(pt.X, pt.Y + deta));
                        }


                    }

                }

                
else
                
{
                    
if (nextsum > 180)
                    
{
                        
if (sum <= 90)
                        
{
                            
// 第一象限,补上小正方形就可以了。
                            g.FillRectangle(Qcommon.b[i % 12], x - deta, y, deta, deta);
                        }

                        
else
                        
{

                            
///// start

                            pt 
= subsidy(g, sum, p, pt, a, b, i, x, y, nextsum);

                            
///// end 
                        }


                        
// 处理180 度
                        if (sum == 180)
                        
{
                            
if (i == 0)
                            
{
                                g.FillPolygon(Qcommon.b[(al.Count 
- 1% 12], new Point[] new Point(pt.X - (int)a, pt.Y), new Point(pt.X - (int)a, pt.Y + deta), pt });
                            }

                            
else
                            
{
                                g.FillPolygon(Qcommon.b[(i 
- 1% 12], new Point[] new Point(pt.X - (int)a, pt.Y), new Point(pt.X - (int)a, pt.Y + deta), pt });
                            }


                        }


                        g.DrawLine(p, 
new Point(pt.X - (int)a, pt.Y), new Point(pt.X - (int)a, pt.Y + deta));

                    }

                    
else
                    
{

                        pt 
= subsidy(g, sum, p, pt, a, b, i, x, y, nextsum);

                    }


                    
// 画底图扇形
                    g.DrawPie(ps, rs, sum, f);
                    
// 画start本处竖线
                    g.DrawLine(p, new Point(x, y), new Point(x, y + deta));


                }


                sum 
= nextsum;

                
//this.saveBitmap("e:\qchart\temp\A" + i.ToString() + ".jpg");

            }
//for

            
int labelWidth = r.Right + deta;
            
int labelHeight = deta;

            sum 
= startAngle % 360;

            
// 画顶面
            for (int i = 0; i <= count; i++)
            
{

                PieData pd 
= (PieData)al[i];
                
float f = Convert.ToSingle(pd.val);

                
int nextsum = sum + Convert.ToInt32(f);


                g.FillPie(Qcommon.b[i 
% 12], r, sum, f);
                g.DrawPie(p, r, sum, f);

                g.FillRectangle(Qcommon.b[i 
% 12], labelWidth, labelHeight, 1010);
                g.DrawString(pd.name, Qcommon.LegendFont, Qcommon.b[i 
% 12], new PointF(labelWidth + 14, labelHeight));

                labelHeight 
+= 16;

                sum 
= nextsum;

                
////this.saveBitmap("e:\qchart\temp\B" + i.ToString() + ".jpg");

            }
//for

           

            
//g.DrawArc(p, rs, 0, 180);

        }


        
private void printSmailRect(Graphics g, int i, Point pend)
        
{
            Brush br 
= null;
            
if (i == count)
                br 
= Qcommon.b[0];
            
else
            
{
                br 
= Qcommon.b[(i>0?(i - 1):i) % 12];
            }


            g.FillRectangle(Qcommon.b[
0], pend.X - deta, pend.Y, deta, deta);

            
        }



        
private Point subsidy(Graphics g, int sum, Pen p, Point pt, double a, double b, int i, int x, int y, int nextsum)
        
{
            Point pend 
= findPoint(nextsum, a, b, pt);

            
// 填充底图扇形
            ////g.FillPie(Qcommon.b[i % 12], rs, sum, f);
            // 补偿三角形 :// 侧面的竖线端点加上前一个位置的上面的顶点

            
if (i == 0)
            
{
                
if (sum <= 90)
                
{
                    
// 第一象限,补上小正方形就可以了。
                    g.FillRectangle(Qcommon.b[0], x - deta, y, deta, deta);
                }

                
else
                
{
                    g.FillPolygon(Qcommon.b[
0], new Point[] new Point(x, y), new Point(x, y + deta), new Point(pt.X + (int)a, pt.Y) });
                }

            }

            
else
            
{
                
//g.FillPolygon(Qcommon.b[i - 1], new Point[] { new Point(x, y), new Point(pend.X, pend.Y + deta), pend });

                
if (sum <= 90)
                
{
                    
// 第一象限,补上小正方形就可以了。
                    g.FillRectangle(Qcommon.b[i % 12], x - deta, y, deta, deta);
                }

                
else
                
{
                    
float pref = Convert.ToSingle(((PieData)al[i - 1]).val);
                    
int presum = sum - Convert.ToInt32(pref);
                    
if (presum < 0) presum += 360;

                    
// 侧面的竖线端点加上前一个位置的上面的顶点
                    Point prept = findPoint(presum, a, b, pt);
                    g.FillPolygon(Qcommon.b[i 
- 1], new Point[] new Point(x, y), new Point(x, y + deta), prept });
                }


            }


            
if (i == count)
            
{
                printLine(g, p, pend);
            }

            
return pt;
        }


        
private void printLine(Graphics g, Pen p, Point pend)
        
{
            g.DrawLine(p,pend,
new Point(pend.X,pend.Y + deta));
        }



        
private Point findPoint(int presum,double a,double b,Point pt)
        
{
            
double af = presum / 180d * Math.PI;
            
int sign = Math.Sign(Math.Cos(af));
            
double k = Math.Tan(af);

            
double dx = sign * Math.Sqrt(1 / (1 / (a * a) + k * k / (b * b)));
            
double dy = k * dx;

            
int x = pt.X + (int)dx;

            
int y = pt.Y + (int)dy;

            
return new Point(x,y);
        }





    }

}

 

using System;
using System.Drawing;
using System.Drawing.Imaging;

namespace qchart
{
    
/// <summary>
    
/// qcommon 的摘要说明。
    
/// </summary>

    public class Qcommon
    
{
        
public static Brush[] b = {   Brushes.Purple,
                                      Brushes.LightSkyBlue,
                                      Brushes.Pink,
                                      Brushes.SeaGreen,
                                      Brushes.Tomato,
                                      Brushes.RoyalBlue,
                                      Brushes.Orange,
                                      Brushes.DarkGray,
                                      Brushes.PowderBlue,
                                      Brushes.OliveDrab,
                                      Brushes.Navy,
                                      Brushes.Magenta
                                  }
;


        
public static Font LegendFont = new Font("宋体"8, FontStyle.Regular);


    }

}

 

using System;

namespace qchart
{
    
/// <summary>
    
/// 饼图的数据格式
    
/// </summary>

    public class PieData
    
{
        
public PieData(double val,string name)
        
{
            
this.val = val ;
            
this.name = name ;
        }


        
public double val;
        
public string name = null;
    }

}



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1645728