C# Visual Studio,在用户单击按钮时绘制Lorenz混沌

C# Visual Studio,在用户单击按钮时绘制Lorenz混沌,c#,graphic,C#,Graphic,所以去年我用C写了一个程序,用洛伦兹方程和龙格库塔方法来解决微分方程,演示了混沌 我最近决定,我想重新审视这一点,并制作一个能够绘制粒子轨迹的程序。我成功地实现了这一点,但现在想扩展它,以便用户可以输入参数,例如粒子的起始位置,以及其他参数(在我的例子中是a、b和r)。目前,程序运行后,我会立即绘制轨迹,但我想推迟,直到用户在一些文本框中输入参数,然后按下按钮。为此,我认为应该创建一个新类并将当前代码放入其中,然后在main.cs文件中的btn1_Click方法下调用它。然而,我在这方面遇到了相

所以去年我用C写了一个程序,用洛伦兹方程和龙格库塔方法来解决微分方程,演示了混沌

我最近决定,我想重新审视这一点,并制作一个能够绘制粒子轨迹的程序。我成功地实现了这一点,但现在想扩展它,以便用户可以输入参数,例如粒子的起始位置,以及其他参数(在我的例子中是a、b和r)。目前,程序运行后,我会立即绘制轨迹,但我想推迟,直到用户在一些文本框中输入参数,然后按下按钮。为此,我认为应该创建一个新类并将当前代码放入其中,然后在main.cs文件中的btn1_Click方法下调用它。然而,我在这方面遇到了相当大的麻烦,主要是不知道如何去做。在我迄今为止最好的尝试中,我遇到了一个与“createGraphics()”相关的行相关的错误,即类文件中没有对它的定义。我在类顶部的using部分中有与主文件中相同的引用,在主文件中它工作得很好

此外,如果有人能给我任何关于我的代码的反馈(如任何不好的做法或我过度复杂的地方)或任何改进建议,我将不胜感激,如果您需要我提供更多信息来帮助,我将尽我所能回答

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Lorenz_chaos
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
        private void Form1_Paint(object sender, PaintEventArgs e)
    {
        double a = 10, b = (8 / 3), r = 28;     //standard values for lorenz model

        /*m defines the number of iterations of the for loop so the number of lines drawn
        good idea to keep m inversely proportional to dt (the time interval). A smaller dt will
        mean smaller lines so smoother overall drawing m=50000 and dt=0.0005 is a good starting point
        that demonstrates chaos well*/
        double m = 500000, dt = 0.00005;

        //EVOLUTION VALUE FOR RUNGE_KUTTA METHOD
        //values for first particle
        double y11, y12, y13;
        double y21, y22, y23;
        double y31, y32, y33;
        double y41, y42, y43;
        double y51, y52, y53;
        double xi, yi, xf, yf;           //coordinates for drawing particle 1 trajectory

        double f10, f11, f12, f13;      //function values to be calculated, 
        double f20, f21, f22, f23;      //for fxy (x>1) these are intermediate fn calculations at different
        double f30, f31, f32, f33;      //times in Runga Kutta

        //values for second particle
        double z11, z12, z13;
        double z21, z22, z23;
        double z31, z32, z33;
        double z41, z42, z43;
        double z51, z52, z53;
        double ai, bi, af, bf;          //coordinates for drawing particle 2 trajectory (these are badly named...)

        double g10, g11, g12, g13;      //equivalent of f values for particle 2 
        double g20, g21, g22, g23;
        double g30, g31, g32, g33;

        //OTHER NEEDED QUANTITIES
        int i;          //for loop iteration integer
        int k1 = 20;    //scaling factors to make drawing fill form
        int k2 = 9;
        int y0 = 450;   //offset values to centre drawing on form
        int x0 = 550;
        int start = 10;   //starting position for calculations
        double diff = 0.01;//initial displacement between two particles

        //starting positions for particles            
        y11 = start;//particle 1
        y12 = start;
        y13 = start;

        z11 = start + diff;//particle 2
        z12 = start + diff;
        z13 = start + diff;

        //initial coords for particles at t=0
        xi = (y11) * k1 + x0;
        yi = (y12) * k2 + y0;
        ai = (z11) * k1 + x0;
        bi = (z12) * k2 + y0;

        for (i = 1; i <= m; i++)
        {
            f10 = a * (y12 - y11);
            f20 = r * y11 - y12 - y11 * y13;
            f30 = y11 * y12 - b * y13;

            y21 = y11 + f10 * dt / 2;               //finding y1 y2 y3 at the first
            y22 = y12 + f20 * dt / 2;               //fraction of dt
            y23 = y13 + f30 * dt / 2;

            f11 = a * (y22 - y21);
            f21 = r * y21 - y22 - y21 * y23;
            f31 = y21 * y22 - b * y23;

            y31 = y11 + f11 * dt / 2;               //finding y1 y2 y3 at the second
            y32 = y12 + f21 * dt / 2;               //fraction of dt
            y33 = y13 + f31 * dt / 2;

            f12 = a * (y32 - y31);
            f22 = r * y31 - y32 - y31 * y33;
            f32 = y31 * y32 - b * y33;

            y41 = y11 + f12 * dt;               //finding y1 y2 y3 at the third
            y42 = y12 + f22 * dt;               //fraction of dt
            y43 = y13 + f32 * dt;

            f13 = a * (y42 - y41);
            f23 = r * y41 - y42 - y41 * y43;
            f33 = y41 * y42 - b * y43;

            y51 = y11 + (f10 + 2 * f11 + 2 * f12 + f13) * dt / 6; //final y values at y(t+dt)
            y52 = y12 + (f20 + 2 * f21 + 2 * f22 + f23) * dt / 6; //then to be repesated in for loop for all steps
            y53 = y13 + (f30 + 2 * f31 + 2 * f32 + f33) * dt / 6;

            xf = (y51) * k1 + x0;
            yf = (y52) * k2 + y0;

            //second particle calculation
            g10 = a * (z12 - z11);
            g20 = r * z11 - z12 - z11 * z13;
            g30 = z11 * z12 - b * z13;

            z21 = z11 + g10 * dt / 2;               //finding y1 y2 y3 at the first
            z22 = z12 + g20 * dt / 2;               //fraction of dt
            z23 = z13 + g30 * dt / 2;

            g11 = a * (z22 - z21);
            g21 = r * z21 - z22 - z21 * z23;
            g31 = z21 * z22 - b * z23;

            z31 = z11 + g11 * dt / 2;               //finding y1 y2 y3 at the second
            z32 = z12 + g21 * dt / 2;               //fraction of dt
            z33 = z13 + g31 * dt / 2;

            g12 = a * (z32 - z31);
            g22 = r * z31 - z32 - z31 * z33;
            g32 = z31 * z32 - b * z33;

            z41 = z11 + g12 * dt;               //finding y1 y2 y3 at the third
            z42 = z12 + g22 * dt;               //fraction of dt
            z43 = z13 + g32 * dt;

            g13 = a * (z42 - z41);
            g23 = r * z41 - z42 - z41 * z43;
            g33 = z41 * z42 - b * z43;

            z51 = z11 + (g10 + 2 * g11 + 2 * g12 + g13) * dt / 6; //final y values at y(t+dt)
            z52 = z12 + (g20 + 2 * g21 + 2 * g22 + g23) * dt / 6; //then to be repesated in for loop for all steps
            z53 = z13 + (g30 + 2 * g31 + 2 * g32 + g33) * dt / 6;

            af = (z51) * k1 + x0;
            bf = (z52) * k2 + y0;


            //DRAWING LINE JUST CALCULATED
            System.Drawing.Graphics graphicsObj;

            graphicsObj = this.CreateGraphics();

            Pen myPen = new Pen(System.Drawing.Color.Red, 1);

            //myPen.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDotDot;

            graphicsObj.DrawLine(myPen, (int)xi, (int)yi, (int)xf, (int)yf);

            myPen.Color = System.Drawing.Color.RoyalBlue;

            graphicsObj.DrawLine(myPen, (int)ai, (int)bi, (int)af, (int)bf);

            //REDEFINING COORDS AND VALUES FOR NEXT LOOP
            //first particle
            xi = (y51) * k1 + x0;
            yi = (y52) * k2 + y0;
            y11 = y51;
            y12 = y52;
            y13 = y53;

            //second particle
            ai = (z51) * k1 + x0;
            bi = (z52) * k2 + y0;
            z11 = z51;
            z12 = z52;
            z13 = z53;

            /*even at 1 the below makes the program far too slow, need an alternative
             intention was for it to allow user to see the particle trajectories better*/
            //System.Threading.Thread.Sleep(1);
        }

    }


}
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统图;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows.Forms;
洛伦兹混沌
{
公共部分类Form1:Form
{
公共表格1()
{
初始化组件();
}
私有void Form1_Paint(对象发送器、PaintEventArgs e)
{
双a=10,b=(8/3),r=28;//洛伦兹模型的标准值
/*m定义for循环的迭代次数,因此绘制的线数
保持m与dt(时间间隔)成反比是个好主意。较小的dt将
平均较小的线,因此更平滑的总体图纸m=50000和dt=0.0005是一个良好的起点
这很好地说明了混乱*/
双m=500000,dt=0.00005;
//龙格库塔法的演化值
//第一个粒子的值
双y11、y12、y13;
双y21、y22、y23;
双y31、y32、y33;
双y41、y42、y43;
双y51、y52、y53;
绘制1粒子轨迹的双席、易、XF、YF、/坐标
双精度f10,f11,f12,f13;//要计算的函数值,
double f20,f21,f22,f23;//对于fxy(x>1),这些是不同条件下的中间fn计算
双f30,f31,f32,f33;//伦加库塔中的次数
//第二个粒子的值
双z11、z12、z13;
双z21,z22,z23;
双z31,z32,z33;
双z41,z42,z43;
双z51、z52、z53;
双ai,双bi,双af,双bf;//绘制粒子2轨迹的坐标(名称不正确…)
双g10,g11,g12,g13;//相当于粒子2的f值
g20、g21、g22、g23双倍增长;
双g30、g31、g32、g33;
//其他所需数量
int i;//对于循环迭代整数
int k1=20;//制作图形填充表单的比例因子
int k2=9;
int y0=450;//表格上图形中心的偏移值
int x0=550;
int start=10;//计算的起始位置
double diff=0.01;//两个粒子之间的初始位移
//粒子的起始位置
y11=开始;//粒子1
y12=启动;
y13=启动;
z11=start+diff;//粒子2
z12=启动+差异;
z13=启动+差异;
//t=0时粒子的初始坐标
席=(Y11)*K1+X0;
yi=(y12)*k2+y0;
ai=(z11)*k1+x0;
bi=(z12)*k2+y0;

对于(i=1;i将
Form1\u Paint
的代码放在一个单独的方法中,例如
DrawLorenzChaos(Graphics Graphics Sobj,double a,double b,double r)
。在表单中设置参数时,只需将一些
bool
值设置为
true
。检查代码

private void Form1_Paint(object sender, PaintEventArgs e)
{  

     if(startDrawing)
           DrawLorenzChaos(e.Graphics, aVal, bVal, rVal);
}
此外,在DrawLorenzChaos方法中,只需删除以下两行:

System.Drawing.Graphics graphicsObj;

graphicsObj = this.CreateGraphics();
编辑:您可以从一开始就尝试这段代码,然后逐步改进,这就是我的做法(我会添加更好的同步,但基本上就是这样)。为了尝试这段代码,您需要一个按钮和一个大小为(10001000)的图片盒。请注意,我稍微更改了开始位置

基本上,这里有一个单独的线程在位图上绘制Lorenz混沌。该位图在UI线程中的PictureBox上绘制,在一个单独的线程中绘制每一行之后。您可以使用互斥来控制对位图的访问

public partial class Form1 : Form
{
    Bitmap offScrBuff;
    Mutex mut;
    int index = 0;
    public Form1()
    {
        InitializeComponent();
        offScrBuff = new Bitmap(1000, 1000);
        mut = new Mutex();
        pictureBox1.Paint += new PaintEventHandler(pictureBox1_Paint);
        button1.Click += new System.EventHandler(this.button1_Click);
    }

    void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        mut.WaitOne();
        e.Graphics.DrawImage(offScrBuff, 0, 0);
        mut.ReleaseMutex();
    }

    void DrawLorenzChaos(double a, double b, double r)
    {
        //double a = 10, b = (8.0 / 3.0), r = 28;     //standard values for lorenz model

        /*m defines the number of iterations of the for loop so the number of lines drawn
        good idea to keep m inversely proportional to dt (the time interval). A smaller dt will
        mean smaller lines so smoother overall drawing m=50000 and dt=0.0005 is a good starting point
        that demonstrates chaos well*/
        double m = 500000, dt = 0.00005;

        //EVOLUTION VALUE FOR RUNGE_KUTTA METHOD
        //values for first particle
        double y11, y12, y13;
        double y21, y22, y23;
        double y31, y32, y33;
        double y41, y42, y43;
        double y51, y52, y53;
        double xi, yi, xf, yf;           //coordinates for drawing particle 1 trajectory

        double f10, f11, f12, f13;      //function values to be calculated, 
        double f20, f21, f22, f23;      //for fxy (x>1) these are intermediate fn calculations at different
        double f30, f31, f32, f33;      //times in Runga Kutta

        //values for second particle
        double z11, z12, z13;
        double z21, z22, z23;
        double z31, z32, z33;
        double z41, z42, z43;
        double z51, z52, z53;
        double ai, bi, af, bf;          //coordinates for drawing particle 2 trajectory (these are badly named...)

        double g10, g11, g12, g13;      //equivalent of f values for particle 2 
        double g20, g21, g22, g23;
        double g30, g31, g32, g33;

        //OTHER NEEDED QUANTITIES
        int i;          //for loop iteration integer
        int k1 = 20;    //scaling factors to make drawing fill form
        int k2 = 9;
        int y0 = 280;   //offset values to centre drawing on form
        int x0 = 400;
        int start = 10;   //starting position for calculations
        double diff = 0.01;//initial displacement between two particles

        //starting positions for particles            
        y11 = start;//particle 1
        y12 = start;
        y13 = start;

        z11 = start + diff;//particle 2
        z12 = start + diff;
        z13 = start + diff;

        //initial coords for particles at t=0
        xi = (y11) * k1 + x0;
        yi = (y12) * k2 + y0;
        ai = (z11) * k1 + x0;
        bi = (z12) * k2 + y0;
        for (i = 1; i <= m; i++)
        {
            f10 = a * (y12 - y11);
            f20 = r * y11 - y12 - y11 * y13;
            f30 = y11 * y12 - b * y13;

            y21 = y11 + f10 * dt / 2;               //finding y1 y2 y3 at the first
            y22 = y12 + f20 * dt / 2;               //fraction of dt
            y23 = y13 + f30 * dt / 2;

            f11 = a * (y22 - y21);
            f21 = r * y21 - y22 - y21 * y23;
            f31 = y21 * y22 - b * y23;

            y31 = y11 + f11 * dt / 2;               //finding y1 y2 y3 at the second
            y32 = y12 + f21 * dt / 2;               //fraction of dt
            y33 = y13 + f31 * dt / 2;

            f12 = a * (y32 - y31);
            f22 = r * y31 - y32 - y31 * y33;
            f32 = y31 * y32 - b * y33;

            y41 = y11 + f12 * dt;               //finding y1 y2 y3 at the third
            y42 = y12 + f22 * dt;               //fraction of dt
            y43 = y13 + f32 * dt;

            f13 = a * (y42 - y41);
            f23 = r * y41 - y42 - y41 * y43;
            f33 = y41 * y42 - b * y43;

            y51 = y11 + (f10 + 2 * f11 + 2 * f12 + f13) * dt / 6; //final y values at y(t+dt)
            y52 = y12 + (f20 + 2 * f21 + 2 * f22 + f23) * dt / 6; //then to be repesated in for loop for all steps
            y53 = y13 + (f30 + 2 * f31 + 2 * f32 + f33) * dt / 6;

            xf = (y51) * k1 + x0;
            yf = (y52) * k2 + y0;

            //second particle calculation
            g10 = a * (z12 - z11);
            g20 = r * z11 - z12 - z11 * z13;
            g30 = z11 * z12 - b * z13;

            z21 = z11 + g10 * dt / 2;               //finding y1 y2 y3 at the first
            z22 = z12 + g20 * dt / 2;               //fraction of dt
            z23 = z13 + g30 * dt / 2;

            g11 = a * (z22 - z21);
            g21 = r * z21 - z22 - z21 * z23;
            g31 = z21 * z22 - b * z23;

            z31 = z11 + g11 * dt / 2;               //finding y1 y2 y3 at the second
            z32 = z12 + g21 * dt / 2;               //fraction of dt
            z33 = z13 + g31 * dt / 2;

            g12 = a * (z32 - z31);
            g22 = r * z31 - z32 - z31 * z33;
            g32 = z31 * z32 - b * z33;

            z41 = z11 + g12 * dt;               //finding y1 y2 y3 at the third
            z42 = z12 + g22 * dt;               //fraction of dt
            z43 = z13 + g32 * dt;

            g13 = a * (z42 - z41);
            g23 = r * z41 - z42 - z41 * z43;
            g33 = z41 * z42 - b * z43;

            z51 = z11 + (g10 + 2 * g11 + 2 * g12 + g13) * dt / 6; //final y values at y(t+dt)
            z52 = z12 + (g20 + 2 * g21 + 2 * g22 + g23) * dt / 6; //then to be repesated in for loop for all steps
            z53 = z13 + (g30 + 2 * g31 + 2 * g32 + g33) * dt / 6;

            af = (z51) * k1 + x0;
            bf = (z52) * k2 + y0;


            //DRAWING LINE JUST CALCULATED

            mut.WaitOne();
            System.Drawing.Graphics graphicsObj = Graphics.FromImage(offScrBuff);

            graphicsObj.DrawLine(Pens.Red, (int)xi, (int)yi, (int)xf, (int)yf);

            graphicsObj.DrawLine(Pens.RoyalBlue, (int)ai, (int)bi, (int)af, (int)bf);

            graphicsObj.Dispose();
            mut.ReleaseMutex();

            pictureBox1.Invalidate();


            //REDEFINING COORDS AND VALUES FOR NEXT LOOP
            //first particle
            xi = (y51) * k1 + x0;
            yi = (y52) * k2 + y0;
            y11 = y51;
            y12 = y52;
            y13 = y53;

            //second particle
            ai = (z51) * k1 + x0;
            bi = (z52) * k2 + y0;
            z11 = z51;
            z12 = z52;
            z13 = z53;
            /*even at 1 the below makes the program far too slow, need an alternative
             intention was for it to allow user to see the particle trajectories better*/
            //System.Threading.Thread.Sleep(1);
        }

    }

    private void button1_Click(object sender, EventArgs e)
    {
        Task.Factory.StartNew(() => { DrawLorenzChaos(10.0, 8.0 / 3.0, 28); });
    }
}
公共部分类表单1:表单
{
位图偏移CRBUFF;
互斥mut;
int指数=0;
公共表格1()
{
初始化组件();
offScrBuff=新位图(10001000);
mut=新的互斥体();
pictureBox1.Paint+=新的PaintEventHandler(pictureBox1\u Paint);
button1.Click+=newsystem.EventHandler(this.button1\u Click);
}
void pictureBox1_Paint(对象发送器,PaintEventArgs e)
{
mut.WaitOne();
e、 Graphics.DrawImage(offScrBuff,0,0);
mut.ReleaseMutex();
}
无效拉深(双a,双b,双r)
{
//双a=10,b=(8.0/3.0),r=28;//洛伦兹模型的标准值
/*m定义for循环的迭代次数,因此绘制的线数
把我留在家里是个好主意