3:ベジエ曲線の長さを求める

曲線の長さを求めたい。 しかし、根号の中が複雑で、数学的には難易度が高そうだ。

ベジエ曲線の長さを求める

曲線の長さを求めるには、積分すればいいが、不定積分ができないことが多く、ベジエ曲線もできなさそうである。

よって、数値計算によって地道に求める必要がある。

定積分のための公式として、台形公式やシンプソンの公式がある。

wikipedia 台形公式

wikipedia シンプソンの公式

台形公式

定積分するということは、積分したい関数のグラフ上で、積分区間の部分の面積を求めることを意味する。

台形公式では、積分区間を刻み数に分け、分割された区間の面積を、台形の面積として近似する。

一つ目の区間が、上図の水色の部分の場合、その面積は(f0+f1)h/2 となる。これを繰り返して合計の面積を求める。

 

シンプソンの公式

台形公式では、分割した部分のグラフを直線として台形の公式で計算したが、シンプソンの公式では、分割した部分を二次曲線として近似する。

3点を通る曲線で近似するので、刻み数は偶数である必要がある。

この図の場合、水色の部分の面積は、(h/3)(f0 + 4f1 + f2) であり、繰り返して全体の面積を求める。

 

関数f の、st~ed の間を、刻み幅h以内で積分する。 hは、刻み数が奇数になってしまった場合には変化する。

class MyMath{
        //積分する
        //シンプソンの公式で積分する
        public delegate double simpsonFunc(double d);
        static public double simpson(double st, double ed, double h, simpsonFunc f)
        {
            //刻み数を決める
            int nh = (int)(Math.Abs((ed - st) / h) + 1.0);
            if (nh % 2 != 07) nh++;
            h = (ed - st) / (nh - 1);

            int cnt;
            double total = 0;
            for (cnt = 0; cnt < nh; cnt++) {
                double tmpadd = f(h * cnt);

                if (cnt == nh - 1) { //最後:そのまま
                } else if (cnt == 0) { //最初:そのまま
                } else if (cnt % 2 != 0) { //奇数
                    tmpadd *= 4;
                } else { //偶数
                    tmpadd *= 2;
                }
                total += tmpadd;
            }
            return h / 3.0 * total;
        }
}

class Bezier{
        // 略・・・

        // 積分したい関数 tを与えると、一番上にある図のルートの部分を計算して返す。
        // d_val は曲線を1回微分した関数
        public double lenfunc(double t) {
            return Math.Sqrt(d_val(t).x * d_val(t).x + d_val(t).y * d_val(t).y);
        }
        // 最大刻み幅hでstからedの長さを求める。積分する関数として lenfunc を与える。
        public double t2l(double st, double ed, double h) {
            return MyMath.simpson(st, ed, h, lenfunc);
        }

        //呼び出し元
        public void moto() {
            t2l(0, 1, 0.00001);
        }

        // ・・・略
}

 

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中