4

変換行列が適用された 2D 楕円の軸に沿ったバウンディング ボックス (AABB) を計算しようとしています (回転、スケール、平行移動など)。

このソリューションに似たもの:変換された球のAABBの計算

これまでのところ、2D 楕円では機能しないようです。

これは私が得たものです(疑似コードで):

Matrix M; // Transformation matrix (already existing)
Matrix C = new Matrix( // Conic matrix
    radiusX, 0,         0,
    0,       radiusY,   0,
    0,       0,         -1
);

Matrix MT = M.transpose();
Matrix CI = C.inverse();

Matrix R = M*CI*MT;

int minX = (R13 + sqrt(R13^2 - (R11 * R33))) / R33;
int minY = (R23 + sqrt(R23^2 - (R22 * R33))) / R33;

// maxX etc...
// Build AABB Rectangle out of min & max...

現在の動作の簡単なデモ

radiusX = 2    
radiusY = 2                              // To keep it simple, M is identity
                                         // (no transformation on the ellipse)
M = /1 0 0\                              // /M11 M21 M31\ 
    |0 1 0|                              // |M12 M22 M32| Transform matrix format
    \0 0 1/                              // \0   0   1  /

C = /2 0  0\                             // C as conic
    |0 2  0|
    \0 0 -1/

CI =/0.5 0   0\                          // CI as dual conic
    |0   0.5 0|
    \0   0  -1/

R = /1 0 0\ * /0.5 0   0\ * /1 0 0\      // R = M*CI*MT
    |0 1 0|   |0   0.5 0|   |0 1 0|
    \0 0 1/   \0   0  -1/   \0 0 1/

  = /0.5 0   0\                          // /R11 R12 R13\
    |0   0.5 0|                          // |R12 R22 R23| (R is symmetric)
    \0   0  -1/                          // \R13 R23 R33/

minX = (0 + sqrt(0^2 - (0.5 * -1))) / -1

     = -0.7071                           // Should be -2

                                         // Also, using R = MIT*C*MI
                                         // leads to -1.4142

ソリューション (デュアル コニック マトリックスを使用)

Matrix M;
Matrix C = new Matrix(
    1/radiusX^2, 0,           0,
    0,           1/radiusY^2, 0,
    0,           0,           -1
);
Matrix MT = M.transpose();
Matrix CI = C.inverse();
Matrix R = M*CI*MT;

int minX = (R13 + sqrt(R13^2 - (R11 * R33))) / R33;
int minY = (R23 + sqrt(R23^2 - (R22 * R33))) / R33;

最終解 (円錐行列を直接使用しない)

ここに簡略化されたバージョンがあります。

Matrix M;

int xOffset = sqrt((M11^2 * radiusX^2) + (M21^2 * radiusY^2));
int yOffset = sqrt((M12^2 * radiusX^2) + (M22^2 * radiusY^2));

int centerX = (M11 * ellipse.x + M21 * ellipse.y) + M31; // Transform center of 
int centerY = (M12 * ellipse.x + M22 * ellipse.y) + M32; // ellipse using M
                                                         // Most probably, ellipse.x = 0 for you, but my implementation has an actual (x,y) AND a translation
int xMin = centerX - xOffset;
int xMax = centerX + xOffset;

int yMin = centerY - yOffset;
int yMax = centerY + yOffset;
4

1 に答える 1

2

二重円錐から

それで、あなたはそれMが変換行列であると述べています。しかし、それは何を変換しますか?それは点ですか、それとも線ですか? ポイントを想定しています。点が左にあり、行列が右にあるように行ベクトルとして、または行列が左にあり、点が乗算の右にあるように列ベクトルとして、点をどのように表現しますか? 列ベクトルを仮定します。したがって、変換はp' = M*pある時点で行われpます。

次はC。書き方は楕円ですが、使用している半径ではありません。点が満たす場合、点は楕円上にある(x/radiusX)^2 + (y/radiusY)^2 = 1ため、主対角線上の値は でなければなりません(1/radiusX^2, 1/radiusY^2, -1)。回答の以前の改訂でこの間違いを繰り返し見逃していました。

次に、これらを組み合わせます。主円錐CP曲線、つまり点の集合としての円錐曲線があるとします。次に、 を実行して、変換されたバージョンを取得しますMT.inverse()*CP*M.inverse()。その理由は、M.inverse()すべての点に適用してから、元の円錐曲線上にあるかどうかを確認するためです。しかしM.inverse()、あなたは を使っていません。あなたは を使っていMます。これは、双対円錐曲線を変換しようとしていることを示しています。Mが点をMT.inverse()変換してから線を変換する場合、 が二重円錐曲線のM*CD*MT場合は正しい変換です。CD

が双対円錐曲線の場合R、式は正しいです。したがって、おそらくコードの主な問題は、行列で逆半径を使用するのを忘れたという事実ですC

原始円錐から

初めてあなたの投稿を読んだとき、R点の集合を説明すると思い(x,y)ました(x,y,1)*R*(x,y,1).transpose()=0。これに基づいて、二重円錐曲線を使用せずに AABB の式を考え出しました。これがより簡単だと言っているわけではありません。特に、構成要素として逆行列を使用できる場合はそうではありません。でも参考までに残しておきます。Rこの段落の は、コード例で使用されているものとは異なることに注意してください。

私のアプローチでは、R*(1,0,0)(これは単純に の最初の列です) は、 line の定義として解釈できるRベクトルであると考えてください。その線を円錐曲線と交差すると、接線が水平になるポイントが得られます。これが方向の極値です。方向の極値を見つけるために (つまり、2 番目の列) についても同じことを行います。(a,b,c)ax+by+c=0yR*(0,1,0)x

ここでの重要なアイデアは、 が特定の point の極線をR*p計算することです。そのpため、それぞれ無限遠点の極線を作成しxます。y方向。その極線は、接線pが円錐曲線に接触する点で円錐曲線と交差します。この場合、これは水平方向です。平行線は無限遠で交差するため、垂直接線。

上記の計算を記号的に行うと、次の式が得られます。

xmin, xmax = (R13*R22^2 - R12*R22*R23 ± sqrt(R13^2*R22^4 - 2*R12*R13*R22^3*R23 + R11*R22^3*R23^2 + (R12^2*R22^3 - R11*R22^4)*R33))/(R12^2*R22 - R11*R22^2)
ymin, ymax = (R11*R12*R13 - R11^2*R23 ± sqrt(R11^3*R13^2*R22 - 2*R11^3*R12*R13*R23 + R11^4*R23^2 + (R11^3*R12^2 - R11^4*R22)*R33))/(R11^2*R22 - R11*R12^2)

これらの式は確かに単純化できますが、開始する必要があります。この投稿をより単純なもの、読みやすいものなどに再構成する場合は、自由に編集してください。

于 2014-07-14T23:08:49.937 に答える