3 次ベジェ曲線スピットの 4 つの制御点を取得するために、曲線に沿っていることがわかっている x、y 座標のリストをプラグインできるアルゴリズムを探していましたが、明らかに見つけられませんでしたアウト。
より正確には、曲線の開始と終了を決定する 2 つの制御点を含む一連の離散点を入力しながら、曲線を形成するために必要な 2 つの制御点を提供するアルゴリズムを探しています。
ありがとう!
編集:さて、古い敵である数学のために、多項式関数に最適なベジエ曲線を求める必要があります。
したがって、エンドポイントが固定されていると仮定すると、3 次ベジエに適合させたい (x,y) サンプル ポイントがいくつかあります。
使用するサンプル ポイントの数によって、どのアプローチを取るかが決まります。いくつかのケースを見てみましょう。
2点
2 つのサンプル ポイントが最も単純なケースです。エンドポイントを数えると、合計4ポイントになります。これは、3 次ベジエの CV の数です。これを解決するには、両方のサンプル ポイントのパラメーター (t) 値が必要です。次に、解決する必要がある 2 つの方程式と 2 つの点からなるシステムが得られます。この方程式は、選択した t 値でのベジエ曲線のパラメトリック方程式です。
t 値は好きなように設定できますが、データに応じて、1/3 と 2/3 のいずれかを使用するか、相対距離またはベースラインに沿った相対距離を調べることで、より良い結果が得られます。
1点
これは 2 点と似ていますが、すべての自由度を一意に決定するには情報が不十分です。私が提案するのは、二次ベジエに適合させてから、次数を上げることです。この質問で二次フィッティングの詳細な例を書きました。
2点以上
この場合、唯一の解決策はありません。最小二乗近似を使用して良好な結果を得ました。手順は次のとおりです。
これらの手順については、この無料の cagd テキストの第 11 章に適切な説明があります。b スプラインのフィッティングについて説明していますが、3 次ベジエは b スプラインの一種です (ノット ベクトルは 0,0,0,1,1, 1 で 4 ポイントあります)。
曲線 y = f(x) があるとしましょう
ベジェ曲線を定義するには、P1x、P1y、P2x、P2y、P3x、P3y、P4x、P4y のような 4 つのポイントが必要です。
P1 と P4 は、曲線の始点/終点です。P2 と P3 はコントロール ポイントです。曲線の始まりと終わりがどこにあるかはすでにわかっています。P2 と P3 を計算する必要があります。t
x 座標の P2x と P3x は簡単です。曲線を 1/3 と 2/3 などに選択して選択するだけだからです。したがって、P2x と P3x が得られます。次に、2 つの方程式と 2 つの未知数 (P2y と P3y) のシステムになります。いくつかの数学をクランチした後、次のような結果になります。
(私の f(x) は 3 次多項式であり、1 つの 3 次ベジエ曲線を正確に当てはめることができることも保証されていました。)
/**
@params {Object} firstPoint = {x:...,y...}
@params {Object} lastPoint = {x:...,y...}
@params {Object} cubicPoly Definition of a cubic polynomial in the form y=ax^3+bx^2+c.
Has a method EvaluateAt, which calculates y for a particular x
*/
var CalcBezierControlPoints = function(firstPoint, lastPoint, cubicPoly) {
var xDiff = lastPoint.X - firstPoint.X;
var x1 = firstPoint.X + xDiff / 3.0;
var x2 = firstPoint.X + 2.0 * xDiff / 3.0;
var y1 = cubicPoly.EvaluateAt(x1);
var y2 = cubicPoly.EvaluateAt(x2);
var f1 = 0.296296296296296296296; // (1-1/3)^3
var f2 = 0.037037037037037037037; // (1-2/3)^3
var f3 = 0.296296296296296296296; // (2/3)^3
var b1 = y1 - firstPoint.Y * f1 - lastPoint.Y / 27.0;
var b2 = y2 - firstPoint.Y * f2 - f3 * lastPoint.Y;
var c1 = (-2 * b1 + b2) / -0.666666666666666666;
var c2 = (b2 - 0.2222222222222 * c1) / 0.44444444444444444;
var p2 = {};
var p3 = {};
p2.X = x1;
p2.Y = c1;
p3.X = x2;
p3.Y = c2;
return ([p2, p3]);
}