您的位置:首页 > 其它

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

2007-10-28 09:22 645 查看
2007年06月09日 18:18:00
点击此处下载源码+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(400, 300);


}




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(400, 300);


}


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(0, 0, 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/2, 400, 300);




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




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


//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, 10, 10);


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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: