ローレンツアトラクタ シミュレータ作った


新装版 カオス力学系の基礎
 Unityちゃんのアセットを落としたけど、アニメーションをどう触っていいのかいまいち理解できないので、かわりにローレンツアトラクタのシミュレータを作ってみた。


 スライダは上からp,r,b。
それぞれの範囲は-20≦p≦20,-50≦r≦50,-5≦b≦5


ローレンツアトラクタはこんな方程式で表現される。
\( \frac{dx}{dt}=-px+py \)
\( \frac{dy}{dt}=rx-xz-y\)
\( \frac{dz}{dt}=xy-bz\)
ただし\(p=10,r=28,b=\frac{8}{3}\)。


 このままだと使いにくいので微分方程式から差分方程式に変える。
\( x_{n+1}=dt(-px+py)+x_{n}\)
\( y_{n+1}=dt(rx-xz-y)+y_{n}\)
\( z_{n+1}=dt(xy-bz)+z_{n}\)
\(x_{0},y_{0},z_{0}\)に初期値を放りこんで順次計算していく。


知ったこと
・[SerializeField]を付ければインスペクタから値を操作できるようになるという噂
・座標の値があまりにも巨大な数か、0除算みたいなことになると、AABBが文句言ってくる。
・AABBが何かは知らない
・座標値があまりにも大きくなるようなら、回避する方法を入れておくほうがいい
・ラインレンダラは頂点座標どうしが離れすぎるとトゲトゲするっぽい


したいこと
・うにてぃchangのアニメーションをどうにかしたい。
・見るだけでいいタイプの広告を入れてみたい

using UnityEngine;
using System.Collections;

public class MakeLine : MonoBehaviour {

    LineRenderer lR;

    //頂点の再計算フラグ
    bool recal = false;

    //Lineの頂点数
    int vCount = 36000;

    //パラメータ
    float p = 10;
    float r = 28;
    float b = 2.66666f;

    #region Sliders value
    float v1 = 1.0f;
    float v2 = 1.0f;
    float v3 = 1.0f;
    float v4 = 1.0f;
    #endregion

    // Use this for initialization
	void Start () {
        this.Initialize();
	}
	
	// Update is called once per frame
	void Update () {
        if (this.recal)
        {
            this.SetVertex();
            this.recal = false;
        }
	
	}

    //初期化
    private void Initialize()
    {

        this.lR = this.GetComponent<LineRenderer>();

        this.lR.SetVertexCount(this.vCount);

        this.recal = true;
    }

    private void SetVertex()
    {
        float x = 1.1f;
        float y = 0.3f;
        float z = 0.0f;
        float xx = 0;
        float yy = 0;
        float zz = 0;
        float dt = 0.1f;

       

        for (int i = 0; i < this.vCount; i++)
        {
            bool f = true;
            int count = 1;
            dt = 0.01f;
            do
            {
                xx = dt * p * (-x + y) + x;
                yy = dt * (x * (-z + r) - y) + y;
                zz = dt * (x * y - b * z) + z;

                if (xx > 500 || yy > 500 || zz > 500 || xx < -500 || yy < -500 || zz < -500) break;

                float l = Mathf.Abs(x * x + y * y + z * z - xx * xx - yy * yy - zz * zz);
                if (l < 0.1f) dt = dt*2.0f;
                else if (l > 1.0f) dt = dt*0.5f;
                else f = false;

                if (count == 5) f = false;
                count++;

            } while (f);

            if (f == true) break;
            x = xx;
            y = yy;
            z = zz;

            xx = 0.1f * xx;
            yy = 0.1f * yy;
            zz = 0.1f * zz;

            this.lR.SetPosition(i, new Vector3(xx, yy, zz));
        }
    }

    #region Get sliders value
    //スライダーの値取得
    public void getSlider1Value(float v)
    {
        //v1 = v;
        p = v;
        this.recal = true;
    }

    public void getSlider2Value(float v)
    {
        //v2 = v;
        r = v;
        this.recal = true;
    }

    public void getSlider3Value(float v)
    {
        //v3 = v;
        b = v;
        this.recal = true;
    }

    public void getSlider4Value(float v)
    {
        v4 = v;
        this.recal = true;
    }
    #endregion