注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Equinox's Blog.

My Naughty Corner

 
 
 

日志

 
 

本周作品: 函數繪製類 for C#  

2010-03-19 22:50:48|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

本周作品: 函數繪製類 for C - Equinox Wong - Equinoxs Blog.

這是用這個類繪製的圖像.

使用前先添加Microsoft Script Control 1.0引用,這是字符串表達式解析的關鍵,其實就是對VBScript的使用...

若你沒有這東西,可到http://www.microsoft.com/downloads/details.aspx?FamilyId=D7E31492-2595-49E6-8C02-1426FEC693AC&displaylang=en下載.

這個類的功能除了繪製圖像外還可以計算函數值或字符串表達式.

下面就是SourceCode,已附XML註釋:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;


/// <summary>
/// 表示一個平面直角坐標系
/// </summary>
    public class Coordinate
    {
        /// <summary>
        /// 表示坐標系中坐標軸的類型
        /// </summary>
        public enum Axis
        {
            /// <summary>
            /// 表示不顯示坐標軸
            /// </summary>
            None = 0,
            /// <summary>
            /// 表示顯示正方形坐標軸
            /// </summary>
            Square = 1,
            /// <summary>
            /// 表示顯示x軸的分度值為pi/2,y軸的分度值為1的三角坐標軸
            /// </summary>
            Trig = -1
        }
        /// <summary>
        /// 表示坐標系中的一個函數
        /// </summary>
        public class Function
        {
            /// <summary>
            /// 函數的表達式
            /// </summary>
            public String Description;
            /// <summary>
            /// 函數自變量的名稱
            /// </summary>
            public String VarName;
            /// <summary>
            /// 繪製函數時使用的Pen對象
            /// </summary>
            public Pen DrawingPen;
            /// <summary>
            /// 初始化Function類的新實例
            /// </summary>
            /// <param name="pen">繪製函數時使用的Pen對象</param>
            /// <param name="Desc">函數的表達式</param>
            /// <param name="Var">函數自變量的名稱</param>
            public Function (Pen pen, String Desc, String Var)
            {
                Description = Desc;
                DrawingPen = pen;
                VarName = Var;
            }
            public override String ToString()
            {
                return Description;
            }
        }
        String Variable;
        System.Collections.ArrayList fns;
        String adc;
        /// <summary>
        /// 設置或獲取在VBScript中進行計算前執行的代碼字符串
        /// </summary>
        public String AdditionalCode
        {
            get
            {
                return adc;
            }
            set
            {
                adc = value;
            }
        }
        /// <summary>
        /// 獲取或設置默認的函數自變量名
        /// </summary>
        public String Varname
        {
            get
            {
                return Variable;
            }
            set
            {
                Variable = value;
            }
        }
        /// <summary>
        /// 獲取函數組成的ArrayList,函數實例可為Coordinate.Function或者System.String
        /// </summary>
        public System.Collections.ArrayList Functions
        {
            get
            {
                return fns;
            }
        }
        /// <summary>
        /// 初始化新的Coordinate實例
        /// </summary>
        public Coordinate()
        {
            Variable = "x";
            fns = new System.Collections.ArrayList(15);
            adc = "Const pi=3.141592653589793\n";
        }
        /// <summary>
        /// 清除函數集合中無效的函數
        /// </summary>
        public void ClearInvalidFunctions()
        {
            MSScriptControl.ScriptControl sc = new MSScriptControl.ScriptControlClass();
            sc.Language = "VBScript";
            for (int i = 0; i < fns.Count;i++ )
            {
                String Expression = fns[i].ToString();
                if (Expression.IndexOf(Variable) == -1)
                {
                    fns.RemoveAt(i);
                    i--;
                    continue;
                }
                try
                {
                    Object obj = sc.Eval(Expression.Replace(Variable, "5"));
                    if (obj == null)
                    {
                        fns.RemoveAt(i);
                        i--;
                    }
                }
                catch (System.Runtime.InteropServices.COMException ce)
                {
                    fns.RemoveAt(i);
                    i--;
                }
                catch
                {
                }
            }
        }
        /// <summary>
        /// 獲取坐標系中所有函數的圖像
        /// </summary>
        /// <param name="MapSize">圖像的長寬大小</param>
        /// <param name="axis">繪製的坐標軸類型</param>
        /// <param name="MidPoint">圖像的中點相對于坐標系的坐標</param>
        /// <param name="PPU">單位長度在圖像中顯示的像素數</param>
        /// <returns>函數的圖像</returns>
        public Bitmap DrawFunction(Size MapSize,Axis axis,Point MidPoint, int PPU)
        {
            MidPoint.Y = -MidPoint.Y;
            Bitmap bm = new Bitmap(MapSize.Width, MapSize.Height);
            MSScriptControl.ScriptControl sc = new MSScriptControl.ScriptControlClass();
            sc.Language = "VBScript";
            if (adc != null)
            {
                try
                {
                    sc.AddCode(adc);
                }
                catch { }
            }
            float PPU2 = PPU;
            float xl = (MapSize.Width / PPU) / 2 - MidPoint.X;
            float xr = (MapSize.Width / PPU) - xl;
            if (axis == Axis.Trig)
            {
                PPU2 = (float)(PPU * 3.141592653589793/2);
                xl = (MapSize.Width / (float)(PPU * 3.141592653589793/2)) / 2 - MidPoint.X;
                xr = (MapSize.Width / (float)(PPU * 3.141592653589793/2)) - xl;
            }

            float yl = (MapSize.Height / PPU) / 2 - MidPoint.Y;
            float yr = (MapSize.Height / PPU) - yl;
            float xlong = (MapSize.Width / PPU) + MidPoint.X;
            float ylong = (MapSize.Height / PPU) - MidPoint.Y;
            String exps = "";
            Graphics g = Graphics.FromImage(bm);
            if (axis != Axis.None)
            {
                try
                {
                    g.DrawString("O", new Font("宋体", 10), new System.Drawing.SolidBrush(Color.Black), new PointF((float)MapSize.Width / 2 - MidPoint.X * PPU, (float)MapSize.Height / 2 + 6 - MidPoint.Y * PPU));
                    g.DrawLine(new Pen(Color.Black), new Point(0, MapSize.Height / 2 - (int)MidPoint.Y * PPU), new Point(MapSize.Width, MapSize.Height / 2 - (int)MidPoint.Y * PPU));
                    g.DrawLine(new Pen(Color.Black), new Point(MapSize.Width, MapSize.Height / 2 - (int)MidPoint.Y * PPU), new Point(MapSize.Width - 6, MapSize.Height / 2 - 5 - (int)MidPoint.Y * PPU));
                    g.DrawLine(new Pen(Color.Black), new Point(MapSize.Width, MapSize.Height / 2 - (int)MidPoint.Y * PPU), new Point(MapSize.Width - 6, MapSize.Height / 2 + 5 - (int)MidPoint.Y * PPU));
                    g.DrawLine(new Pen(Color.Black), new Point(MapSize.Width / 2 - (int)MidPoint.X * PPU, 0), new Point(MapSize.Width / 2 - (int)MidPoint.X * PPU, MapSize.Height));
                    g.DrawLine(new Pen(Color.Black), new Point(MapSize.Width / 2 - (int)MidPoint.X * PPU, 0), new Point(MapSize.Width / 2 - 5 - (int)MidPoint.X * PPU, 6));
                    g.DrawLine(new Pen(Color.Black), new Point(MapSize.Width / 2 - (int)MidPoint.X * PPU, 0), new Point(MapSize.Width / 2 + 5 - (int)MidPoint.X * PPU, 6));
                    for (int x1 = 1; x1 < xr; x1++)
                    {
                        String x1s=x1.ToString();
                        if (axis==Axis.Trig) {
                            x1s=(((double)x1)/2).ToString()+"π";
                        }
                        g.DrawString(x1s, new Font("宋体", 10), new System.Drawing.SolidBrush(Color.Black), new PointF(((float)x1 * PPU2 - 7 + MapSize.Width / 2 - MidPoint.X * PPU), ((float)MapSize.Height / 2 + 6 - MidPoint.Y * PPU)));
                        g.DrawLine(new Pen(Color.Black), new Point((int)(x1 * PPU2 + MapSize.Width / 2 - MidPoint.X * PPU), (int)(MapSize.Height / 2 - MidPoint.Y * PPU)), new Point((int)(x1 * PPU2 + MapSize.Width / 2 - MidPoint.X * PPU), (int)(MapSize.Height / 2 + 4 - MidPoint.Y * PPU)));
                    }
                    for (int x2 = 1; x2 < xl; x2++)
                    {
                        String x2s = (-x2).ToString();
                        if (axis == Axis.Trig)
                        {
                            x2s = (((double)-x2) / 2).ToString() + "π";
                        }
                        g.DrawString(x2s, new Font("宋体", 10), new System.Drawing.SolidBrush(Color.Black), new PointF(((float)-x2 * PPU2 - 7 + MapSize.Width / 2 - MidPoint.X * PPU), ((float)MapSize.Height / 2 + 6 - MidPoint.Y * PPU)));
                        g.DrawLine(new Pen(Color.Black), new Point((int)(-x2 * PPU2 + MapSize.Width / 2 - MidPoint.X * PPU), (int)(MapSize.Height / 2 - MidPoint.Y * PPU)), new Point((int)(-x2 * PPU2 + MapSize.Width / 2 - MidPoint.X * PPU), (int)(MapSize.Height / 2 + 4 - MidPoint.Y * PPU)));
                    }
                    for (int y1 = 1; y1 < yl; y1++)
                    {
                        g.DrawString(y1.ToString(), new Font("宋体", 10), new System.Drawing.SolidBrush(Color.Black), new PointF(((float)MapSize.Width / 2 + 6 - MidPoint.X * PPU), ((float)(-y1) * PPU - 7 + MapSize.Height / 2 - MidPoint.Y * PPU)));
                        g.DrawLine(new Pen(Color.Black), new Point((int)(MapSize.Width / 2 - MidPoint.X * PPU), (int)(-y1 * PPU + MapSize.Height / 2 - MidPoint.Y * PPU)), new Point((int)(MapSize.Width / 2 + 4 - MidPoint.X * PPU), (int)(-y1 * PPU + MapSize.Height / 2 - MidPoint.Y * PPU)));
                    }
                    for (int y2 = 1; y2 < yr; y2++)
                    {
                        g.DrawString((-y2).ToString(), new Font("宋体", 10), new System.Drawing.SolidBrush(Color.Black), new PointF(((float)MapSize.Width / 2 + 6 - MidPoint.X * PPU), ((float)y2 * PPU - 7 + MapSize.Height / 2 - MidPoint.Y * PPU)));
                        g.DrawLine(new Pen(Color.Black), new Point((int)(MapSize.Width / 2 - MidPoint.X * PPU), (int)(y2 * PPU + MapSize.Height / 2 - MidPoint.Y * PPU)), new Point((int)(MapSize.Width / 2 + 4 - MidPoint.X * PPU), (int)(y2 * PPU + MapSize.Height / 2 - MidPoint.Y * PPU)));
                    }
                }
                catch { }
            }
            Point laspnt;
            laspnt = new Point();

            foreach (Object obj in fns)
            {
                Pen pn = new Pen(Color.Blue);
                String vr = Variable;
                Type typ = obj.GetType();

                if (typ.FullName == "Coordinate+Function")
                {
                    vr = ((Function)obj).VarName;
                    pn = ((Function)obj).DrawingPen;
                }
                bool pnt = false;
                String Expression = obj.ToString();
                if (Expression == "") continue;
                for (int x = 0; x < MapSize.Width; x++)
                {

                    int y;
                    try
                    {
                        exps = Expression.Replace(Variable, ((((double)x) - ((double)MapSize.Width) / 2.0+MidPoint.X*PPU) / (double)PPU).ToString());
                        Object ob = sc.Eval(exps);
                        double ns = Convert.ToDouble(ob);
                        y = (int)(-ns * PPU + (MapSize.Height) / 2-MidPoint.Y*PPU);
                    }
                    catch (System.Runtime.InteropServices.COMException ee)
                    {
                        if (ee.ErrorCode != -2146828283)
                        {
                            goto END;
                        }
                        else
                        {
                            continue;
                        }
                    }
                    if (x == 0)
                    {
                        laspnt = new Point(x, y);
                        pnt = true;
                        continue;
                    }
                    Point thispnt = new Point(x, y);
                    if (pnt == false)
                    {
                        laspnt = thispnt;
                        pnt = true;
                        continue;
                    }
                    try
                    {
                        if (Math.Abs(thispnt.Y - laspnt.Y) < MapSize.Height)
                        {
                            g.DrawLine(pn, laspnt, thispnt);
                        }
                        laspnt = thispnt;
                    }
                    catch { }
                }
            END: ;

            }
            return bm;
        }
        /// <summary>
        /// 獲取坐標系中所有函數的圖像
        /// </summary>
        /// <param name="MapSize">圖像的長寬大小</param>
        /// <param name="PPU">單位長度在圖像中顯示的像素數</param>
        /// <returns>函數的圖像</returns>
        public Bitmap DrawFunction(Size MapSize, int PPU)
        {
            return DrawFunction(MapSize,Axis.Square,new Point(0,0),PPU);
        }
        /// <summary>
        /// 計算指定的表達式
        /// </summary>
        /// <param name="Expression">表達式</param>
        /// <returns>計算結果</returns>
        public Object Compute(String Expression)
        {
            MSScriptControl.ScriptControl sc = new MSScriptControl.ScriptControlClass();
            sc.Language = "VBScript";
            if (adc != null)
            {
                sc.AddCode(adc);
            }
            return sc.Eval(Expression);
        }
        /// <summary>
        /// 計算坐標系中某一函數的函數值
        /// </summary>
        /// <param name="FnIndex">函數在函數集合中的索引</param>
        /// <param name="Var">自變量的值</param>
        /// <returns>計算結果</returns>
        public Object Compute(int FnIndex, String Var)
        {
            String vr = Variable;
            Type typ=Functions[FnIndex].GetType();
            if (typ.FullName == "Coordinate+Function")
            {
                vr = ((Function)Functions[FnIndex]).VarName;
            }
            return Compute(Functions[FnIndex].ToString().Replace(vr, Var));
        }
    }

 

 

  评论这张
 
阅读(382)| 评论(4)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017