using System; using System.Linq; namespace Bezier { /// <summary> /// 計算されたベジェ曲線の座標データを保持するクラス /// 点ベースと軸ベース、両方のアクセス方法を提供します。 /// </summary> public class BezierCurveResult { /// <summary> /// 点ベースの座標配列。 /// Points[点のインデックス][次元のインデックス] /// (例: 3番目の点の座標配列全体が欲しい場合は Points[3]) /// </summary> public double[][] Points { get; } /// <summary> /// 軸ベースの座標配列。 /// Axes[次元のインデックス][点のインデックス] /// (例: X軸のすべての点の座標配列が欲しい場合は Axes[0]) /// </summary> public double[][] Axes { get; } public BezierCurveResult(int pointCount, int dimension) { // 点ベースのジャグ配列を初期化 Points = new double[pointCount][]; for (int i = 0; i < pointCount; i++) { Points[i] = new double[dimension]; } // 軸ベースのジャグ配列を初期化 Axes = new double[dimension][]; for (int d = 0; d < dimension; d++) { Axes[d] = new double[pointCount]; } } } /// <summary> /// n次元に対応した3次ベジェ曲線クラス /// </summary> public class BezierCurve { public double[] Anchor1 { get; set; } public double[] Handle1 { get; set; } public double[] Handle2 { get; set; } public double[] Anchor2 { get; set; } public int Dimension { get { return Anchor1?.Length ?? 0; } } public BezierCurve(double[] anchor1, double[] handle1, double[] handle2, double[] anchor2) { int dim = anchor1.Length; if (handle1.Length != dim || handle2.Length != dim || anchor2.Length != dim) { throw new ArgumentException("すべてのポイントは同じ次元数(配列の長さ)である必要があります。"); } Anchor1 = anchor1; Handle1 = handle1; Handle2 = handle2; Anchor2 = anchor2; } /// <summary> /// 曲線を指定した数で分割し、点ベース・軸ベース両方の配列を持った結果オブジェクトを返します。 /// </summary> public BezierCurveResult CalculatePoints(int segments) { if (segments <= 0) { throw new ArgumentException("分割数は1以上にしてください。", nameof(segments)); } int dim = Dimension; int pointCount = segments + 1; // 戻り値用の専用オブジェクトを作成 var result = new BezierCurveResult(pointCount, dim); for (int i = 0; i <= segments; i++) { double t = (double)i / segments; double u = 1.0 - t; double coeff0 = u * u * u; double coeff1 = 3 * u * u * t; double coeff2 = 3 * u * t * t; double coeff3 = t * t * t; for (int d = 0; d < dim; d++) { // 座標を計算 double val = coeff0 * Anchor1[d] + coeff1 * Handle1[d] + coeff2 * Handle2[d] + coeff3 * Anchor2[d]; // 点ベースの配列に代入 result.Points[i][d] = val; // 軸ベースの配列にも同じ値を代入 result.Axes[d][i] = val; } } return result; } } }