情報学部 菅沼ホーム 目次 索引

補間法(ベジエ曲線)

    1. A. C++
    2. B. Java
    3. C. JavaScript
    4. D. PHP
    5. E. Ruby
    6. F. Python
    7. G. C#
    8. H. VB

  プログラムは,ベジエ多角形を B0 = (1 1),B1 = (2 3),B2 = (4 3),B3 = (3 1) としたとき,対応するベジエ曲線を描くためのものです.

  1. C++

    /****************************/
    /* n次ベジエ曲線           */
    /*      coded by Y.Suganuma */
    /****************************/
    #include <stdio.h>
    
    double *Bezier(int, double **, double);
    
    int main()
    {
    	double **B, t, step = 0.05, *P;
    	int i1, n;
    					// 設定
    	n = 3;
    	B = new double *[n+1];
    	for (i1 = 0; i1 <= n; i1++)
    		B[i1] = new double [2];
    
    	B[0][0] = 1.0;
    	B[0][1] = 1.0;
    	B[1][0] = 2.0;
    	B[1][1] = 3.0;
    	B[2][0] = 4.0;
    	B[2][1] = 3.0;
    	B[3][0] = 3.0;
    	B[3][1] = 1.0;
    					// 実行と出力
    	t = 0.0;
    	for (i1 = 0; i1 <= 20; i1++) {
    		P = Bezier(n, B, t);
    		printf("%f %f %f\n", t, P[0], P[1]);
    		t += step;
    	}
    
    	for (i1 = 0; i1 <= n; i1++)
    		delete [] B[i1];
    	delete [] B;
    	delete [] P;
    
    	return 0;
    }
    
    /*******************************/
    /* n次ベジエ曲線              */
    /*      n : 次数               */
    /*      B : 多角形の頂点座標   */
    /*      t : 計算したい点の位置 */
    /*      return : 座標          */
    /*      coded by Y.Suganuma    */
    /*******************************/
    double brend(int, int, double);
    double kaijo(int);
    
    double *Bezier(int n, double **B, double t)
    {
    	double *P, J;
    	int i;
    					// 初期設定
    	P    = new double [2];
    	P[0] = 0.0;
    	P[1] = 0.0;
    					// 計算
    	for (i = 0; i <= n; i++) {
    		J     = brend(n, i, t);
    		P[0] += B[i][0] * J;
    		P[1] += B[i][1] * J;
    	}
    
    	return P;
    }
    
    /*******************************/
    /* ベジエ基底関数              */
    /*      n,i : 次数             */
    /*      t : 計算したい点の位置 */
    /*      return : 結果          */
    /*******************************/
    double brend(int n, int i, double t)
    {
    	double ni, x = 1.0, y = 1.0;
    	int i1;
    
    	ni = kaijo(i) * kaijo(n-i);
    	ni = kaijo(n) / ni;
    
    	for (i1 = 1; i1 <= i; i1++)
    		x *= t;
    	t = 1.0 - t;
    	for (i1 = 1; i1 <= n-i; i1++)
    		y *= t;
    
    	return ni * x * y;
    }
    
    /*****************/
    /* nの階乗の計算 */
    /*****************/
    double kaijo(int n)
    {
    	double k = 1.0;
    	int i1;
    
    	if (n > 1) {
    		for (i1 = 2; i1 <= n; i1++)
    			k *= i1;
    	}
    
    	return k;
    }
    			

  2. Java

    /****************************/
    /* n次ベジエ曲線           */
    /*      coded by Y.Suganuma */
    /****************************/
    import java.io.*;
    
    public class Test {
    	public static void main(String args[]) throws IOException
    	{
    		double B[][], t, step = 0.05, P[];
    		int i1, n;
    					// 設定
    		n = 3;
    		B = new double [n+1][2];
    
    		B[0][0] = 1.0;
    		B[0][1] = 1.0;
    		B[1][0] = 2.0;
    		B[1][1] = 3.0;
    		B[2][0] = 4.0;
    		B[2][1] = 3.0;
    		B[3][0] = 3.0;
    		B[3][1] = 1.0;
    					// 実行と出力
    		t = 0.0;
    		for (i1 = 0; i1 <= 20; i1++) {
    			P = bezier(n, B, t);
    			System.out.println(t + " " + P[0] + " " + P[1]);
    			t += step;
    		}
    	}
    
    	/*******************************/
    	/* n次ベジエ曲線              */
    	/*      n : 次数               */
    	/*      B : 多角形の頂点座標   */
    	/*      t : 計算したい点の位置 */
    	/*      return : 座標          */
    	/*      coded by Y.Suganuma    */
    	/*******************************/
    	static double [] bezier(int n, double B[][], double t)
    	{
    		double P[], J;
    		int i;
    					// 初期設定
    		P    = new double [2];
    		P[0] = 0.0;
    		P[1] = 0.0;
    					// 計算
    		for (i = 0; i <= n; i++) {
    			J     = brend(n, i, t);
    			P[0] += B[i][0] * J;
    			P[1] += B[i][1] * J;
    		}
    
    		return P;
    	}
    
    	/*******************************/
    	/* ベジエ基底関数              */
    	/*      n,i : 次数             */
    	/*      t : 計算したい点の位置 */
    	/*      return : 結果          */
    	/*******************************/
    	static double brend(int n, int i, double t)
    	{
    		double ni, x = 1.0, y = 1.0;
    		int i1;
    
    		ni = kaijo(i) * kaijo(n-i);
    		ni = kaijo(n) / ni;
    
    		for (i1 = 1; i1 <= i; i1++)
    			x *= t;
    		t = 1.0 - t;
    		for (i1 = 1; i1 <= n-i; i1++)
    			y *= t;
    
    		return ni * x * y;
    	}
    
    	/*****************/
    	/* nの階乗の計算 */
    	/*****************/
    	static double kaijo(int n)
    	{
    		double k = 1.0;
    		int i1;
    
    		if (n > 1) {
    			for (i1 = 2; i1 <= n; i1++)
    				k *= i1;
    		}
    
    		return k;
    	}
    }
    			

  3. JavaScript

      ここをクリックすると,任意のデータに対して,ベジエ曲線上の座標を画面上に出力することができます.
    <!DOCTYPE HTML>
    
    <HTML>
    
    <HEAD>
    
    	<TITLE>補間法(ベジエ曲線)</TITLE>
    	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    	<SCRIPT TYPE="text/javascript">
    		function main()
    		{
    					// データの設定
    			let n  = parseInt(document.getElementById("order").value);
    			let sp = parseFloat(document.getElementById("step").value);
    			let B  = new Array();
    			for (let i1 = 0; i1 < n+1; i1++)
    				B[i1]  = new Array();
    			let s = (document.getElementById("data").value).split(/ {1,}|\n{1,}/);
    			let k = 0;
    			for (let i1 = 0; i1 < 2*(n+1); i1 += 2) {
    				B[k][0] = parseFloat(s[i1]);
    				B[k][1] = parseFloat(s[i1+1]);
    				k++;
    			}
    			let P = new Array();
    					// 出力
    			let str = "";
    			let t = 0.0;
    			while (t < 1.0+0.01*sp) {
    				P = Bezier(n, B, t);
    				str = str + "x " + P[0] + " y " + P[1] + "\n";
    				t += sp;
    			}
    			document.getElementById("ans").value = str;
    		}
    
    		/*******************************/
    		/* n次ベジエ曲線              */
    		/*      n : 次数               */
    		/*      B : 多角形の頂点座標   */
    		/*      t : 計算したい点の位置 */
    		/*      return : 座標          */
    		/*      coded by Y.Suganuma    */
    		/*******************************/
    		function Bezier(n, B, t)
    		{
    			let P = new Array();
    			P[0] = 0.0;
    			P[1] = 0.0;
    			let J;
    			let i;
    						// 計算
    			for (i = 0; i <= n; i++) {
    				J     = brend(n, i, t);
    				P[0] += B[i][0] * J;
    				P[1] += B[i][1] * J;
    			}
    
    			return P;
    		}
    
    		/*******************************/
    		/* ベジエ基底関数              */
    		/*      n,i : 次数             */
    		/*      t : 計算したい点の位置 */
    		/*      return : 結果          */
    		/*******************************/
    		function brend(n, i, t)
    		{
    			let ni;
    			let x = 1.0;
    			let y = 1.0;
    			let i1;
    
    			ni = kaijo(i) * kaijo(n-i);
    			ni = kaijo(n) / ni;
    
    			for (i1 = 1; i1 <= i; i1++)
    				x *= t;
    			t = 1.0 - t;
    			for (i1 = 1; i1 <= n-i; i1++)
    				y *= t;
    
    			return ni * x * y;
    		}
    
    		/*****************/
    		/* nの階乗の計算 */
    		/*****************/
    		function kaijo(n)
    		{
    			let k = 1.0;
    			let i1;
    
    			if (n > 1) {
    				for (i1 = 2; i1 <= n; i1++)
    					k *= i1;
    			}
    
    			return k;
    		}
    	</SCRIPT>
    
    </HEAD>
    
    <BODY STYLE="font-size: 130%; background-color: #eeffee;">
    
    	<H2 STYLE="text-align:center"><B>補間法(ベジエ曲線)</B></H2>
    
    	<DL>
    		<DT>  テキストフィールドおよびテキストエリアには,例として,ベジエ多角形を B<SUB>0</SUB> = (1 1),B<SUB>1</SUB> = (2 3),B<SUB>2</SUB> = (4 3),B<SUB>3</SUB> = (3 1) としたときの値が設定されています.他の問題を実行する場合は,それらを適切に修正してください.
    	</DL>
    
    	<DIV STYLE="text-align:center">
    		次数(n):<INPUT ID="order" STYLE="font-size: 100%" TYPE="text" SIZE="2" VALUE="3"> 
    		ステップ:<INPUT ID="step" STYLE="font-size: 100%;" TYPE="text" SIZE="5" VALUE="0.05"> 
    		<BUTTON STYLE="font-size: 100%; background-color: pink" onClick="main()">OK</BUTTON><BR><BR>
    		頂点座標(x y,(n+1)個):<TEXTAREA ID="data" COLS="30" ROWS="15" STYLE="font-size: 100%">1.0 1.0
    2.0 3.0
    4.0 3.0
    3.0 1.0</TEXTAREA><BR><BR>
    		<TEXTAREA ID="ans" COLS="50" ROWS="15" STYLE="font-size: 100%"></TEXTAREA>
    	</DIV>
    
    </BODY>
    
    </HTML>
    			

  4. PHP

    <?php
    
    /****************************/
    /* n次ベジエ曲線           */
    /*      coded by Y.Suganuma */
    /****************************/
    
    					// 設定
    	$step = 0.05;
    	$n    = 3;
    	$B    = array($n+1);
    	for ($i1 = 0; $i1 <= $n; $i1++)
    		$B[$i1] = array(2);
    
    	$B[0][0] = 1.0;
    	$B[0][1] = 1.0;
    	$B[1][0] = 2.0;
    	$B[1][1] = 3.0;
    	$B[2][0] = 4.0;
    	$B[2][1] = 3.0;
    	$B[3][0] = 3.0;
    	$B[3][1] = 1.0;
    					// 実行と出力
    	$t = 0.0;
    	for ($i1 = 0; $i1 <= 20; $i1++) {
    		$P = Bezier($n, $B, $t);
    		printf("%f %f %f\n", $t, $P[0], $P[1]);
    		$t += $step;
    	}
    
    /*******************************/
    /* n次ベジエ曲線              */
    /*      n : 次数               */
    /*      B : 多角形の頂点座標   */
    /*      t : 計算したい点の位置 */
    /*      return : 座標          */
    /*      coded by Y.Suganuma    */
    /*******************************/
    function Bezier($n, $B, $t)
    {
    					// 初期設定
    	$P    = array(2);
    	$P[0] = 0.0;
    	$P[1] = 0.0;
    					// 計算
    	for ($i = 0; $i <= $n; $i++) {
    		$J     = brend($n, $i, $t);
    		$P[0] += $B[$i][0] * $J;
    		$P[1] += $B[$i][1] * $J;
    	}
    
    	return $P;
    }
    
    /*******************************/
    /* ベジエ基底関数              */
    /*      n,i : 次数             */
    /*      t : 計算したい点の位置 */
    /*      return : 結果          */
    /*******************************/
    function brend($n, $i, $t)
    {
    	$x  = 1.0;
    	$y  = 1.0;
    	$ni = kaijo($i) * kaijo($n-$i);
    	$ni = kaijo($n) / $ni;
    
    	for ($i1 = 1; $i1 <= $i; $i1++)
    		$x *= $t;
    	$t = 1.0 - $t;
    	for ($i1 = 1; $i1 <= $n-$i; $i1++)
    		$y *= $t;
    
    	return $ni * $x * $y;
    }
    
    /*****************/
    /* nの階乗の計算 */
    /*****************/
    function kaijo($n)
    {
    	$k = 1.0;
    
    	if ($n > 1) {
    		for ($i1 = 2; $i1 <= $n; $i1++)
    			$k *= $i1;
    	}
    
    	return $k;
    }
    
    ?>
    			

  5. Ruby

    #***************************/
    # n次ベジエ曲線           */
    #      coded by Y.Suganuma */
    #***************************/
    
    #******************************/
    # n次ベジエ曲線              */
    #      n : 次数               */
    #      B : 多角形の頂点座標   */
    #      t : 計算したい点の位置 */
    #      return : 座標          */
    #      coded by Y.Suganuma    */
    #******************************/
    def Bezier(n, b, t)
    					# 初期設定
    	p = [0.0, 0.0]
    					# 計算
    	for i in 0 ... n+1
    		j     = brend(n, i, t)
    		p[0] += b[i][0] * j
    		p[1] += b[i][1] * j
    	end
    
    	return p
    end
    
    #******************************/
    # ベジエ基底関数              */
    #      n,i : 次数             */
    #      t : 計算したい点の位置 */
    #      return : 結果          */
    #******************************/
    def brend(n, i, t)
    	x = 1.0
    	y = 1.0
    	ni = kaijo(i) * kaijo(n-i)
    	ni = kaijo(n) / ni
    
    	for i1 in 1 ... i+1
    		x *= t
    	end
    	t = 1.0 - t
    	for i1 in 1 ... n-i+1
    		y *= t
    	end
    
    	return ni * x * y
    end
    
    #****************/
    # nの階乗の計算 */
    #****************/
    def kaijo(n)
    	k = 1.0
    
    	if n > 1
    		for i1 in 2 ... n+1
    			k *= i1
    		end
    	end
    
    	return k
    end
    
    					# 設定
    step = 0.05
    n    = 3
    b    = [[1.0, 1.0], [2.0, 3.0], [4.0, 3.0], [3.0, 1.0]]
    					# 実行と出力
    t    = 0.0
    for i1 in 0 ... 21
    	p = Bezier(n, b, t)
    	printf("%f %f %f\n", t, p[0], p[1])
    	t += step
    end
    			

  6. Python

    # -*- coding: UTF-8 -*-
    import numpy as np
    from math import *
    
    ###############################
    # n次ベジエ曲線
    #      n : 次数
    #      B : 多角形の頂点座標
    #      t : 計算したい点の位置
    #      return : 座標
    #      coded by Y.Suganuma
    ################################
    
    def Bezier(n, B, t) :
    
    			# 初期設定
    	P = np.array([0, 0,], np.float)
    			# 計算
    	for i in range(0, n+1) :
    		J     = brend(n, i, t)
    		P[0] += B[i][0] * J
    		P[1] += B[i][1] * J
    
    	return P
    
    ##############################
    # ベジエ基底関数
    #      n,i : 次数
    #      t : 計算したい点の位置
    #      return : 結果
    ##############################
    
    def brend(n, i, t) :
    
    	x = 1.0
    	y = 1.0
    
    	ni = kaijo(i) * kaijo(n-i)
    	ni = kaijo(n) / ni
    
    	for i1 in range(1, i+1) :
    		x *= t
    	t = 1.0 - t
    	for i1 in range(1, n-i+1) :
    		y *= t
    
    	return (ni * x * y)
    
    ################
    # nの階乗の計算
    ################
    
    def kaijo(n) :
    
    	k = 1.0
    	if n > 1 :
    		for i1 in range(2, n+1) :
    			k *= i1
    	return k
    
    ############################
    # n次ベジエ曲線
    #      coded by Y.Suganuma
    ############################
    			# 設定
    step = 0.05
    n    = 3
    B    = np.array([[1, 1], [2, 3], [4, 3], [3, 1]], np.float)
    t    = 0.0
    			# 実行と出力
    for i1 in range(0, 21) :
    	P = Bezier(n, B, t)
    	print(t, P[0], P[1])
    	t += step
    			

  7. C#

    /****************************/
    /* n次ベジエ曲線           */
    /*      coded by Y.Suganuma */
    /****************************/
    using System;
    
    class Program
    {
    	static void Main()
    	{
    		Test1 ts = new Test1();
    	}
    }
    
    class Test1
    {
    	public Test1()
    	{
    					// 設定
    		int n = 3;
    		double[][] B = new double [n+1][];
    		B[0] = new double[] {1.0, 1.0};
    		B[1] = new double[] {2.0, 3.0};
    		B[2] = new double[] {4.0, 3.0};
    		B[3] = new double[] {3.0, 1.0};
    					// 実行と出力
    		double t    = 0.0;
    		double step = 0.05;
    		for (int i1 = 0; i1 <= 20; i1++) {
    			double[] P = bezier(n, B, t);
    			Console.WriteLine(t + " " + P[0] + " " + P[1]);
    			t += step;
    		}
    	}
    
    	/*******************************/
    	/* n次ベジエ曲線              */
    	/*      n : 次数               */
    	/*      B : 多角形の頂点座標   */
    	/*      t : 計算したい点の位置 */
    	/*      return : 座標          */
    	/*      coded by Y.Suganuma    */
    	/*******************************/
    	 double[] bezier(int n, double[][] B, double t)
    	{
    					// 初期設定
    		double[] P = {0.0, 0.0};
    					// 計算
    		for (int i = 0; i <= n; i++) {
    			double J = brend(n, i, t);
    			P[0] += B[i][0] * J;
    			P[1] += B[i][1] * J;
    		}
    
    		return P;
    	}
    
    	/*******************************/
    	/* ベジエ基底関数              */
    	/*      n,i : 次数             */
    	/*      t : 計算したい点の位置 */
    	/*      return : 結果          */
    	/*******************************/
    	double brend(int n, int i, double t)
    	{
    		double ni = kaijo(n) / (kaijo(i) * kaijo(n-i));
    
    		double x = 1.0;
    		for (int i1 = 1; i1 <= i; i1++)
    			x *= t;
    		double y = 1.0;
    		t        = 1.0 - t;
    		for (int i1 = 1; i1 <= n-i; i1++)
    			y *= t;
    
    		return (ni * x * y);
    	}
    
    	/*****************/
    	/* nの階乗の計算 */
    	/*****************/
    	double kaijo(int n)
    	{
    		double k = 1.0;
    
    		if (n > 1) {
    			for (int i1 = 2; i1 <= n; i1++)
    				k *= i1;
    		}
    
    		return k;
    	}
    }
    			

  8. VB

    ''''''''''''''''''''''''''''
    ' n次ベジエ曲線           '
    '      coded by Y.Suganuma '
    ''''''''''''''''''''''''''''
    Module Test
    
    	Sub Main()
    					' 設定
    		Dim n As Integer = 3
    		Dim B(,) = {{1.0, 1.0}, {2.0, 3.0}, {4.0, 3.0}, {3.0, 1.0}}
    					' 実行と出力
    		Dim t As Double  = 0.0
    		Dim sp As Double = 0.05
    		For i1 As Integer = 0 To 20
    			Dim P() As Double = bezier(n, B, t)
    			Console.WriteLine(t & " " & P(0) & " " & P(1))
    			t += sp
    		Next
    
    	End Sub
    
    	'''''''''''''''''''''''''''''''
    	' n次ベジエ曲線              '
    	'      n : 次数               '
    	'      B : 多角形の頂点座標   '
    	'      t : 計算したい点の位置 '
    	'      return : 座標          '
    	'      coded by Y.Suganuma    '
    	'''''''''''''''''''''''''''''''
    	 Function bezier(n As Integer, B(,) As Double, t As Double)
    
    					' 初期設定
    		Dim P() As Double = {0.0, 0.0}
    					' 計算
    		For i As Integer = 0 To n
    			Dim J As Double = brend(n, i, t)
    			P(0) += B(i,0) * J
    			P(1) += B(i,1) * J
    		Next
    
    		Return P
    
    	End Function
    
    	'''''''''''''''''''''''''''''''
    	' ベジエ基底関数              '
    	'      n,i : 次数             '
    	'      t : 計算したい点の位置 '
    	'      return : 結果          '
    	'''''''''''''''''''''''''''''''
    	Function brend(n As Integer, i As Integer, t As Double)
    
    		Dim ni As Double = kaijo(n) / (kaijo(i) * kaijo(n-i))
    		Dim x As Double  = 1.0
    
    		For i1 As Integer = 1 To i
    			x *= t
    		Next
    		Dim y As Double = 1.0
    		t = 1.0 - t
    		For i1 As Integer = 1 To n-i
    			y *= t
    		Next
    
    		Return (ni * x * y)
    
    	End Function
    
    	'***************'
    	' nの階乗の計算 '
    	'***************'
    	Function kaijo(n As Integer)
    
    		Dim k As Double = 1.0
    
    		If n > 1
    			For i1 As Integer = 2 To n
    				k *= i1
    			Next
    		End If
    
    		Return k
    
    	End Function
    
    End Module
    			

情報学部 菅沼ホーム 目次 索引