3

DirectX ピクセル シェーダーで、放物線上の任意の点に最も近い点を 2d で見つけようとしています。

大量のグーグル検索により、これが一般的な計算前の宿題の問題であることが明らかになりました。残念ながら、何百もの関連する回答はすべて、「この方程式が得られたら、グラフ電卓の最小関数を使用すると、答えが 6 であることがわかります。」

計算前のことは何も覚えていないことを告白します。私が探している方程式はおそらくウィキペディアにあると思いますが、これらのギリシャ記号を HLSL 関数に変換する方法がわかりません。C、C++、C#、またはその他の言語でのソリューションも大歓迎です。

編集:入力曲線の形式を確認するリクエストごと:

//Equation of parabola being y = ax^2 + bx + c
//p is the arbitrary point we're trying to find the closest point on the parabola for.
float2 GetClosestPointOnParabola(float a, float b, float c, float2 p)
{
    //Something involving the distance formula...
    //Something involving "minimization"...
    return float2(x, y);
} 
4

2 に答える 2

3

あなたはこれを利用することができます:

Pmin = (xmin, ymin) ~ point on a parabola
P = (px, py) ~ point in 2d    
y = a*x^2 + bx + c ~ parabola

P(x) = (x-px)^2 + (y-py)^2 = (x-px)^2 + (a*x^2 + bx + c - py)^2

P(x)導関数を計算する必要がありますが、それほど難しくはありません。たとえばP(x) = x^4 + 4x^2 - 3x + 10、次のようになります。導関数は次のようになります。

P'(x) = 4x^3 + 8x - 3

私はあなたがそれを計算する方法を理解していると思います。次に、P'(x)をゼロと比較して、X軸と交差する場所を見つけます。あなたはそれからxminを見つけ、それからあなたはからyminを持っています:

y = a*x^2 + bx + c

それでおしまい。

于 2012-03-21T07:55:54.233 に答える
0

あなたが望むのは、平面内の別の点に最も近い放物線上の点だと思います。放物線が で与えられ、点 A(x a , y ay = a * x^2 + b * x + c )に最も近い放物線上の点を見つけたいと仮定しましょう。

山登りを使うことをお勧めします。対数的複雑度を持つ関数で極小値を見つけます。放物線上の x に等しい x 座標を持つ点で、A から点までの距離を計算する関数 h(x) があると仮定して、c++ コードの例を記述します。

double minDist() {
  const double epsylon = 1e-9; // used to avoid double prescision errors
  double current = 0.0;
  double step = 1e+6;
  while (step > 1e-5) { // change this with the accuracy you need
    double left_neighbour = current - step;
    double right_neighbour = current + step;
    double cval = h(current);
    double lval = h(left_neighbour);
    double rval = h(right_neighbour);
    if (cval < rval + epsylon && cval < lval + epsylon) {
      step *= 0.5;
      continue;
    }
    if (lval < rval) {
      current = left_neighbour;
    } else {
      current = right_neighbour;
    }
  }
  return current;
}

ほとんどの場合、必要な答えである単一のローカル最小値がありますが、2つある場合もあります(2つ以上になることはできないと思います)。このような場合、異なる初期点で関数を 2 回開始する必要があります。

お役に立てれば。

于 2012-03-21T08:09:58.673 に答える