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

news/2024/6/30 23:20:33

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

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

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


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

    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
{
    
/// 
    
/// 饼图的抽象类,所有样式的饼图继承此类
    
/// 

    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
{
    
/// 
    
/// 
    
/// 

    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
{
    
/// 
    
/// 
    
/// 

    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
{
    
/// 
    
/// qcommon 的摘要说明。
    
/// 

    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
{
    
/// 
    
/// 饼图的数据格式
    
/// 

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


        
public double val;
        
public string name = null;
    }

}





http://www.niftyadmin.cn/n/3650739.html

相关文章

.net实现3D饼图

1 实现原理&#xff1a;根据各个数据的比重画扇形组成一个椭圆&#xff08;柱体的上表面&#xff09;&#xff0c;实现2D饼图()&#xff0c;设定一个厚度h&#xff08;柱体的高度&#xff09;&#xff0c;在距离此柱体的上表面下方h处画一个同样的椭圆。然后将侧面的可见区域[0…

如何在Windows NT中隐藏自己[转]

导读&#xff1a; [ 在NT“盒子”里消失 ] 如何在Windows NT中隐藏自己 -------------------------- 作者&#xff1a;Holy_Father 版本&#xff1a;1.2 英语 日期&#xff1a;05.08.2003 翻译&#xff1a;pker / CVC翻译小组 [ 1. 目录 ] 1. 目录 2. 介绍 3. 文件 3.1 NtQuery…

[asp,jsp,asp.net]文件上传技术浅议~~

文件上传是一个很有意义的话题.我将就 其原理和实际应用 以及安全的设计方面进行初步的讨论..当一个form表单 被设置为enctype&#xff02;MULTIPART/FORM-DATA&#xff02; method&#xff02;post&#xff02; 时,其中的〈input type&#xff02;file&#xff02; name&#…

.Net环境下基于Ajax的MVC方案

.Net环境下基于Ajax的MVC方案 1、问题背景现在&#xff0c;越来越多人开始尝试基于Ajax进行无刷新的Web开发&#xff0c;不过&#xff0c;在.Net环境下&#xff0c;应用Ajax并不是非常方便&#xff0c;这主要可能是由以下一些原因造成的&#xff1a;由于Ajax基于javascript的本…

[转载]后门工具gina源代码

导读&#xff1a; 信息来源&#xff1a;bingle之家 文章作者&#xff1a;bingle /* NTShellGINA.c - a gina stub come from NTShell 1.0 by&#xff1a;bingleemail.com.cn, from homepage:bingle_site.top263.net This file is modified from microsoft sample ginastub.c, t…

简单的方式由数据库的物理表(TABLE)生成实体类(DTO)

步骤&#xff1a;通过DataBaseMetaData一次获取想要的各个表和相关的列信息。再分析各个列的类型&#xff0c;生成文件。---------------------------------------------------------------------------------------------------非常简单&#xff0c;只需要读一次数据库&#x…

查看完整版本: 使用C语言编写提取通用shellcode的程序

导读&#xff1a; 使用C语言编写提取通用shellcode的程序文章修改&#xff1a;Hume/冷雨飘心 文章注释&#xff1a;我非我[F.S.T] 信息来源&#xff1a;黑客基地 [code]/* 说明&#xff1a;此程序可以用标准c语言string格式打印出你所在ShellCodes函数中编写的shellcode 用vc编…