我在10月份发表过一篇随笔“画函数图形的C#程序,兼论一个病态函数”,在那篇随笔中写道:
这个画函数图形的C#程序有一个严重的缺点,就是函数表达式是直接写的源程序中的,不能象SciLab和Matlab那样交互式地输入。 后来,根据“空间/IV”的评论,我写了个动态生成用户输入的函数表达式的类,用以改进这个画函数图形的C#程序。下面是该程序的运行效果:


可以看到,不但要画的函数的表达式可以由用户动态地输入,而且函数自变量的范围也可以是常量表达式。 下面就是源程序:

// plot.cs: 画函数图形, 编译方法: csc /t:winexe plot.cs Expression.cs
using System;
using System.Drawing;
using System.Windows.Forms;
using Skyiv.Util;

namespace Skyiv.Ben.Plot
{
  sealed class PlotForm : Form
  {
    const int yBase = 24; // 屏幕保留区域的高度

    TextBox tbxX0, tbxX1;  // 函数自变量的取值范围
    TextBox tbxExpression; // 函数的表达式
    
    PlotForm()
    {
      SuspendLayout();
      
      Button btnSubmit = new Button();
      btnSubmit.Text = "刷新";
      btnSubmit.Location = new Point(0, 0);
      btnSubmit.Size = new Size(48, 24);
      btnSubmit.Click += new EventHandler(BtnSubmit_Click);

      tbxX0 = new TextBox();
      tbxX0.Text = "-Math.PI";
      tbxX0.Location = new Point(55, 3);
      tbxX0.Size = new Size(100, 20);

      tbxX1 = new TextBox();
      tbxX1.Text = "Math.PI";
      tbxX1.Location = new Point(160, 3);
      tbxX1.Size = new Size(100, 20);

      tbxExpression = new TextBox();
      tbxExpression.Text = "Math.Sin(x)";
      tbxExpression.Location = new Point(265, 3);
      tbxExpression.Size = new Size(335, 20);
      tbxExpression.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right);

      Controls.AddRange(new Control[]{btnSubmit, tbxX0, tbxX1, tbxExpression});
      Text = "Plot";
      BackColor = Color.White;
      ClientSize = new Size(600, 600 + yBase);
      // WindowState = FormWindowState.Maximized;

      ResumeLayout(false);
    }

    // 点击“刷新”按钮时重绘程序主窗口
    void BtnSubmit_Click(object sender, EventArgs e)
    {
      Invalidate();
    }
    
    /**//*
    // 因为本程序使用 C# 的反射功能动态生成数学表达式并计算其值
    // 所以重画时有点慢,如果你的计算机的速度不是非常快的,
    // 就不要在窗口改变大小时强制重绘,而是通过点击发“刷新”按钮重绘。
    protected override void OnSizeChanged(EventArgs e)
    {
      Invalidate();
      base.OnSizeChanged(e);
    }
    */
    
    protected override void OnPaint(PaintEventArgs e)
    {
      Graphics gc = e.Graphics;
      try
      {
        double x0 = new Expression(tbxX0.Text).Compute(0);
        double x1 = new Expression(tbxX1.Text).Compute(0);
        Size size = ClientSize;
        int i0 = 0;
        int i1 = size.Width - 1;
        int j0 = yBase;
        int j1 = size.Height - 1;
        Pen pen = new Pen(Color.Black, 1);
        gc.DrawLine(pen, i0, j0, i1, j0); // 画图区和保留区的分界线
        double rx = (x1 - x0) / (i1 - i0);
        double y0, y1;
        Expression fx = new Expression(tbxExpression.Text);
        GetFunctionValueRange(fx, x0, rx, i0, i1, out y0, out y1);
        double ry = (y1 - y0) / (j1 - j0);
        Out(gc, 0, "ClientSize: {0}x{1}", i1 - i0 + 1, j1 - j0 + 1);
        Out(gc, 1, "f(x): " + tbxExpression.Text);
        Out(gc, 2, "x:[{0}, {1}] range:{2}", x0, x1, x1 - x0);
        Out(gc, 3, "y:[{0}, {1}] range:{2}", y0, y1, y1 - y0);
        Out(gc, 4, "rx:{0}", 1 / rx);  // 函数自变量每单位值用多少个象素表示
        Out(gc, 5, "ry:{0}", 1 / ry);  // 函数的值每单位值用多少个象素表示
        Out(gc, 6, "r :{0}", rx / ry); // 该值如果小于1表示图形纵向被压扁,反之则被拉伸
        pen.Color = Color.Green;
        int j = j1 + (int)(y0 / ry);
        if (j >= j0 && j <= j1) gc.DrawLine(pen, i0, j, i1, j); // x坐标轴
        int i = i0 - (int)(x0 / rx);
        if (i >= i0 && i <= i1) gc.DrawLine(pen, i, j0, i, j1); // y坐标轴
        pen.Color = Color.Red;
        for (i = i0; i <= i1; i++)
        {
          double x = x0 + (i - i0) * rx;
          double y = fx.Compute(x);
          if (double.IsInfinity(y) || double.IsNaN(y)) continue;
          j = j1 - (int)((y - y0) / ry);
          if (j > j1 || j < j0) continue;
          gc.DrawLine(pen, i, j, i + 1, j); // 画函数的图形
        }
      }
      catch (Exception ex)
      {
        Out(gc, 0, ex.Message);
      }
      base.OnPaint(e);
    }
    
    // 函数值的取值范围
    void GetFunctionValueRange(Expression fx, double x0, double rx, int i0, int i1, out double y0, out double y1)
    {
      y0 = double.MaxValue;
      y1 = double.MinValue;
      for (int i = i0; i <= i1; i++)
      {
        double x = x0 + (i - i0) * rx;
        double y = fx.Compute(x);
        if (double.IsInfinity(y) || double.IsNaN(y)) continue;
        if (y0 > y) y0 = y;
        if (y1 < y) y1 = y;
      }
    }
    
    // 在指定的位置写字符串
    void Out(Graphics gc, int line, string fmt, params object [] args)
    {
      gc.DrawString(string.Format(fmt, args), new Font("Courier New", 10), Brushes.Blue, new PointF(5, yBase + 15 * line));
    }

    static void Main()
    {
      Application.Run(new PlotForm());
    }
  }
}

转载于:https://www.cnblogs.com/gjahead/archive/2007/08/18/861164.html

画函数图形的C#程序(改进版) (转)相关推荐

  1. 用matlab画出ex,如何用matlab画函数图形

    1.首先打开matlab应用程序,输入下方的代码:2.然后按确定会出现一张图,如下图所示,这就是 怎么用matlab画函数图形?请看下面方法. 方法 打开Matlab. r0=5;b=1;t0=2;s ...

  2. 用matlab绘制函数图形,matlab函数绘制 用matlab怎样绘制函数图形

    用matlab怎样绘制函数图形 函数f(x1,x2)= x1*cos x2*sin x1+x2*x2*sin x2*cos x1 0≤xi≤2∏的图形?x=0:0.1:2*pi; y=x; [x,y] ...

  3. matlab中怎么画函数曲线,用matlab 怎么画函数曲线图

    matlab的数据处理能力很强大,这款软件还能绘制各种函数图形.下面我将介绍用matlab画函数图形的方法,以在同一张图上画出y1=sin(x)和y2=sin^2(x)的图形为例. 工具/原料 mat ...

  4. 怎么用python画sin函数图像_Python3使用Matplotlib 绘制精美的数学函数图形

    记录Python3使用Matplotlib 绘制精美的数学图形. 一个最最简单的例子: 绘制一个从 0 到 360 度完整的 SIN 函数图形 import numpy as np import ma ...

  5. python画方波_今天学会傅里叶画画,明天就是初音未来 - 如何用Python和Blender画任意图形...

    前言: 最近在[编程德鲁伊]的[傅里叶级数可视化]章节中,练习了傅里叶级数基础原理的可视化,演示了周期方波曲线,可以分解为一系列正弦波曲线: 这次拿学到的知识做个实验,试试喜闻乐见的[用傅里叶级数画画 ...

  6. 单叶双曲面MATLAB编程,在matlab中画函数(x^2+y^2)/9-z^2/4=1的旋转单叶双曲面

    答:>> [x,y]=meshgrid(-10:0.1:10); z=2*sqrt((x.^2+y.^2)/9-1); z((x.^2+y.^2)/9-1 答:-1.5:0.1:1.5; ...

  7. matlab已知函数表达式画函数图像,怎么用matlab画已知函数表达式的一个函数图像?函数比较复杂的……...

    点击查看怎么用matlab画已知函数表达式的一个函数图像?函数比较复杂的--具体信息 答:要具体哦,如果一个自变量,函数图像就是曲线,用plot 如果是2个自变量,函数图像就是曲面了,如f=3*exp ...

  8. C语言 函数图形绘制系统

    系统功能简述: 初等函数曲线图形的简易绘制:设屏幕显示文本是25行, 80列,可以用"+"和"--〉"号画坐标系,用"*"号画曲线上的点.用 ...

  9. 在Authorware中实现动态函数图像绘制的程序实现过程

    2019独角兽企业重金招聘Python工程师标准>>> 使用过由Macromadia公司出品的Authorware多媒体制作软件的设计师们,都应该会知道其实他是一款非常强大的功能全面 ...

最新文章

  1. BZOJ2957:楼房重建(线段树)
  2. 如何计算一年总共有多少周_美国计算机CS专业一年需要多少留学费用?
  3. iOS - OC NSSize 尺寸
  4. C和C++里的const常量、volatile修饰符的深层次说明
  5. 如何将加密PDF转换成Word文档
  6. MySQL命令梳理_MySQL操作命令梳理(1)
  7. 来入门一下kotlin吧
  8. NA-NP-IE系列实验28:HDLC 和PPP 封装
  9. 3D Computer Grapihcs Using OpenGL - 18 相机移动
  10. quartus仿真29:JK触发器实现序列信号发生器0010111(分析)
  11. Mac电脑上非常好用的英汉互译词典软件
  12. UML(Unified Modeling Language) 统一建模语言
  13. 配电室智能监控系统设计及实现分析
  14. 冯诺依曼计算机设备,科学网—计算机学习漫谈(10)——一台冯·诺依曼机器 - 陈钊的博文...
  15. 快乐大本营html5小游戏,快乐大本营小游戏规则-新年小游戏.doc
  16. 什么是开发平台? 几句话就让你明白!
  17. jbox弹窗_jbox很好的弹出层 很好的弹出层 - 下载 - 搜珍网
  18. 网络中的计算机如果加入家庭组,win7如何加入家庭组
  19. 410款INTEL CPU详细技术资料速查表
  20. 操作系统第6次实验报告:使用信号

热门文章

  1. C语言通过printf()设置输出显示方式
  2. 东华大学计算机学院讲座单,计信学院成功举办2018级专业导师面对面系列讲座活动...
  3. 有没有code能改xml内容_Spring源码解析-applicationContext.xml加载和bean的注册
  4. 内蒙古高考2021年成绩查询,内蒙古招生考试信息网:2021年内蒙古高考查分入口、查分系统...
  5. linux nc命令测试端口,Linux和Windows下的NC(Netcat)命令测试端口连通性
  6. MySQL倒序如何避免filesort_如何避免mysql查询的filesort?
  7. 1040 有几个PAT(PAT乙级 C++)
  8. 电力、市政、交通三大领域推动工业交换机行业发展
  9. 网络监控系统中如何选择工业交换机?
  10. 【渝粤题库】国家开放大学2021春2704植物学基础题目