非常好的一篇文章,Graph of Function

本文介绍了一个使用C#编写的函数图形绘制程序。该程序允许用户输入函数表达式并定义绘图范围及颜色,能自动识别函数定义域,并支持多种基本运算和三角函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文:http://www.codeproject.com/Articles/713686/Graph-of-Function

Introduction

My program allows you to build a graph of a function given a string. In the program the user himself defines the boundaries within which there is a graph of the construction and function of the color line. To change the priority operations can use parentheses. The program examines the construction schedule affiliation argument domain of the function. Therefore, the graph is constructed only in locations that are the domain of the function. You can build any number of graphics functions, setting for each color display. You can change and delete functions are introduced.

Windows

The main program window.

Window entry functions.

Architecture

The program works in the following way change a character string, a list of tokens, syntax tree. Character string is a collection of some symbols that represent operations, functions, numbers, parentheses, variables x and constants pi and e token . List of tokens is a list of instances of classes that implement the interface Isintahnode. Syntax tree is a tree whose nodes are operations, functions, numbers, constants and variables are in accordance with the priority of their implementation.

Graph drawing takes place on the panel using the methods of class Graphics.

Using the code

Interface ISyntaxNode describes the behavior of token. Method GetResult returns result for this token. Method IsDomainOfFunction checks whether the value of x belongs to the domain of definition of the token. Method ToStringValue returns the symbol for the token.

public interface ISyntaxNode
{
    string ToStringValue();
    double GetResult(double x);
    bool IsDomainOfFunction(double x);
}  

Class Function that inherits the interface ISyntaxNode.

abstract class Function: ISyntaxNode
{
    private ISyntaxNode x;
    public Function()
    {
    }

    public Function(ISyntaxNode x)
    {
        this.x = x;
    }
    public  ISyntaxNode GetX()
    {
        return x;
    }

    public void SetX(ISyntaxNode x)
    {
        this.x = x;
    }

    public abstract double GetResult(double x);
    public abstract bool IsDomainOfFunction(double x);
    public abstract string ToStringValue();

}

Class Sin that inherits from the class Function and implements the abstract methods.

class Sin: Function
{
    public Sin(): base()
    {
    }

    public Sin(ISyntaxNode x): base (x)
    {
    }

    public override double GetResult(double x)
    {
        return Math.Sin(GetX().GetResult(x));
    }

    public override bool IsDomainOfFunction(double x)
    {
        return GetX().IsDomainOfFunction(x);
    }

    public override string ToStringValue()
    {
        return "sin";
    }
}

Attributes of the class SyntaxTree that performs build syntax tree.

listOperations - is a list conventional signs operations and functions that support the program.

listBynaryOperations - is a list conventional signs binary operations that support the program.

listUnaryOperations - is a list conventional signs unary operations that support the program.

listFunctions - is a list conventional signs functions that support the program.

root - is the root of syntax trees.

static List<string> listOperations = new List<string>(new string[] { "+", "-", "*", "/", "--", "^", "sin", "cos", "tan", "ctg", "log", "abs"});
static List<string> listBinaryOperations = new List<string>(new string[] { "+", "-", "*", "/", "^"});
static List<string> listUnaryOperations = new List<string>(new string[] {"--" });
static List<string> listFunctions = new List<string>(new string[] { "sin", "cos", "tan", "ctg", "log", "abs" });
private ISyntaxNode root;   

Method BuildSyntaxTree that performs build syntax tree. Method takes one parameter, which contains a list of tokens and return operations or functions with the lowest priority.

private ISyntaxNode BuildSyntaxTree(List<ISyntaxNode> listNode)
{
    DeleteExcessiveBrackets(listNode);
    if (listNode.Count == 1)  return listNode[0];

    int position;
    ISyntaxNode  min = FindMinPrioritiOperation(listNode, out position);
    if (listBinaryOperations.IndexOf(min.ToStringValue()) != -1)
    {
        BinaryOperation operation = min as BinaryOperation;
        operation.SetA(BuildSyntaxTree(listNode.GetRange(0, position)));
        operation.SetB(BuildSyntaxTree(listNode.GetRange(position + 1,listNode.Count - (position +1))));
    }
    if (listUnaryOperations.IndexOf(min.ToStringValue()) != -1)
    {
        UnaryOperation operation = min as UnaryOperation;
        operation.SetA(BuildSyntaxTree(listNode.GetRange(position + 1, listNode.Count - (position + 1))));
    }
    if (listFunctions.IndexOf(min.ToStringValue()) != -1)
    {
        Function function = min as Function;
        function.SetX(BuildSyntaxTree(listNode.GetRange(position + 1, listNode.Count - (position + 1))));
    }
    return min;
}

Method DeleteExcessiveBrackets deletes excessive brackets. Sample: expression before executing the method - ((9-x)*17-2); expression after execution method - (9-x)*17-2.

Method FindMinPrioritiOperation seeking operation is the lowest priority. Sample: expression - (9-x)*17-2; result - operation - and position 7.

Drawing graphics

private void DrawFunction(string function, Color functionColor)
{
    int sizeX = panelGraphFunction.Size.Width;
    int sizeY = panelGraphFunction.Size.Height;
    double minX = -10, maxX = 10;
    double minY = -10, maxY = 10;

    minX = Convert.ToDouble(textBoxMinX.Text);
    maxX = Convert.ToDouble(textBoxMaxX.Text);
    minY = Convert.ToDouble(textBoxMinY.Text);
    maxY = Convert.ToDouble(textBoxMaxY.Text);

    SyntaxTree calculator = new SyntaxTree(function);

    Graphics g = panelGraphFunction.CreateGraphics();

    Point currentPoint = new Point();
    Point previousPoint = new Point();
    bool isCurentPoint = false;
    bool isPreviousPoint = false;
    for (double x = minX; x < maxX; x += (maxX - minX) / sizeX)
    {
        double y = calculator.Calculate(x, out isCurentPoint);
        if (Math.Abs(y) > maxY * 2) isCurentPoint = false;
        if (isCurentPoint)
        {
            currentPoint.X = (int)(x / ((maxX - minX) / sizeX) - minX / ((maxX - minX) / (double)sizeX));
            currentPoint.Y = (int)(sizeY - (y / ((maxY - minY) / sizeY) - minY / ((maxY - minY) / (double)sizeY)));
            if (isPreviousPoint)
            {
                g.DrawLine(new Pen(functionColor, 2), previousPoint, currentPoint);
            }
        }
        previousPoint = currentPoint;
        isPreviousPoint = isCurentPoint;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值