21

独自の VML 形式に基づく Internet Explorer の SVG 実装に取り​​組んでいるときに、SVG 楕円弧を VML 楕円弧に変換するという問題に直面しました。

VML では、弧は次のように与えられます: 楕円上の 2 点の 2 つの角度と半径の長さ SVG では、弧は次のように与えられます: 楕円上の 2 点の 2 組の座標と楕円境界ボックスのサイズ

問題は、楕円上の 2 点の角度を 2 組の座標にどのように表現するかです。中間の質問は次のようなものです: 楕円の曲線上の点のペアの座標によって楕円の中心を見つける方法。

更新:楕円が通常配置されている(その半径は線形座標系の軸に平行である)という前提条件があるため、回転は適用されません。

更新: この質問は svg:ellipse 要素とは関係がなく、svg:path 要素の「a」楕円弧コマンド ( SVG パス: 楕円弧曲線コマンド)とは関係ありません。

4

5 に答える 5

27

したがって、解決策は次のとおりです。

楕円のパラメーター化された式:

x = x0 + a * cos(t)
y = y0 + b * sin(t)

それに 2 点の既知の座標を入れましょう:

x1 = x0 + a * cos(t1)
x2 = x0 + a * cos(t2)
y1 = y0 + b * sin(t1)
y2 = y0 + b * sin(t2)

これで、楕円の中心 (x0/y0) と 2 つの角度 t1、t2 の 4 つの変数を持つ連立方程式ができました。

中心座標を取り除くために方程式を引きましょう:

x1 - x2 = a * (cos(t1) - cos(t2))
y1 - y2 = b * (sin(t1) - sin(t2))

これは次のように書き直すことができます (積和恒等式を使用)。

(x1 - x2) / (2 * a) = sin((t1 + t2) / 2) * sin((t1 - t2) / 2)
(y2 - y1) / (2 * b) = cos((t1 + t2) / 2) * sin((t1 - t2) / 2)

いくつかの方程式を置き換えてみましょう:

r1: (x1 - x2) / (2 * a)
r2: (y2 - y1) / (2 * b)
a1: (t1 + t2) / 2
a2: (t1 - t2) / 2

次に、単純な方程式系を取得します。

r1 = sin(a1) * sin(a2)
r2 = cos(a1) * sin(a2)

最初の式を 2 番目で割ると、次のようになります。

a1 = 逆正接 (r1/r2)

この結果を最初の式に追加すると、次のようになります。

a2 = arcsin(r2 / cos(arctan(r1/r2)))

または、単純な (三角関数と逆三角関数の組み合わせを使用):

a2 = arcsin(r2 / (1 / sqrt(1 + (r1/r2)^2)))

またはさらに単純です:

a2 = arcsin(sqrt(r1^2 + r2^2))

これで、最初の 4 つの方程式系を簡単に解決でき、すべての角度と日食の中心座標を見つけることができます。

于 2008-10-13T16:13:34.883 に答える
8

あなたが投稿した楕円曲線の弧のリンクには、楕円弧の実装に関する注意事項へのリンクが含まれています。

そこには、エンドポイントから中心のパラメータ化への変換の式があります。

これは、 Sylvester.jsを使用して行列とベクトルの計算を実行する楕円弧パスの対話型デモから取得した、これらの方程式の JavaScript 実装です。

// Calculate the centre of the ellipse
// Based on http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
var x1 = 150;  // Starting x-point of the arc
var y1 = 150;  // Starting y-point of the arc
var x2 = 400;  // End x-point of the arc
var y2 = 300;  // End y-point of the arc
var fA = 1;    // Large arc flag
var fS = 1;    // Sweep flag
var rx = 100;  // Horizontal radius of ellipse
var ry =  50;  // Vertical radius of ellipse
var phi = 0;   // Angle between co-ord system and ellipse x-axes

var Cx, Cy;

// Step 1: Compute (x1′, y1′)
var M = $M([
               [ Math.cos(phi), Math.sin(phi)],
               [-Math.sin(phi), Math.cos(phi)]
            ]);
var V = $V( [ (x1-x2)/2, (y1-y2)/2 ] );
var P = M.multiply(V);

var x1p = P.e(1);  // x1 prime
var y1p = P.e(2);  // y1 prime


// Ensure radii are large enough
// Based on http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters
// Step (a): Ensure radii are non-zero
// Step (b): Ensure radii are positive
rx = Math.abs(rx);
ry = Math.abs(ry);
// Step (c): Ensure radii are large enough
var lambda = ( (x1p * x1p) / (rx * rx) ) + ( (y1p * y1p) / (ry * ry) );
if(lambda > 1)
{
    rx = Math.sqrt(lambda) * rx;
    ry = Math.sqrt(lambda) * ry;
}


// Step 2: Compute (cx′, cy′)
var sign = (fA == fS)? -1 : 1;
// Bit of a hack, as presumably rounding errors were making his negative inside the square root!
if((( (rx*rx*ry*ry) - (rx*rx*y1p*y1p) - (ry*ry*x1p*x1p) ) / ( (rx*rx*y1p*y1p) + (ry*ry*x1p*x1p) )) < 1e-7)
    var co = 0;
else
    var co = sign * Math.sqrt( ( (rx*rx*ry*ry) - (rx*rx*y1p*y1p) - (ry*ry*x1p*x1p) ) / ( (rx*rx*y1p*y1p) + (ry*ry*x1p*x1p) ) );
var V = $V( [rx*y1p/ry, -ry*x1p/rx] );
var Cp = V.multiply(co);

// Step 3: Compute (cx, cy) from (cx′, cy′)
var M = $M([
               [ Math.cos(phi), -Math.sin(phi)],
               [ Math.sin(phi),  Math.cos(phi)]
            ]);
var V = $V( [ (x1+x2)/2, (y1+y2)/2 ] );
var C = M.multiply(Cp).add(V);

Cx = C.e(1);
Cy = C.e(2);
于 2012-07-13T08:55:19.200 に答える
3

楕円は 2 点だけでは定義できません。円 (特殊なケースの楕円) でさえ、3 つの点で定義されます。

3 つのポイントがあっても、これらの 3 つのポイントを通過する無限の楕円ができます (考えてみましょう: 回転)。

境界ボックスは楕円の中心を示しており、ほとんどの場合、楕円の長軸と短軸が x、y (または y、x) 軸に平行であると想定していることに注意してください。

于 2008-10-13T14:03:50.353 に答える
1

中級者向けの質問はかなり簡単ですが、そうではありません。境界ボックスから楕円の中心を計算します (つまり、楕円がボックスの中心にある限り、ボックスの中心は楕円の中心です)。

最初の質問については、ウィキペディアで入手できる楕円方程式の極形式を調べます。楕円の離心率も計算する必要があります。

または、バウンディング ボックスから値をブルート フォースすることもできます...ポイントが楕円上にあり、角度と一致するかどうかを調べ、バウンディング ボックス内のすべてのポイントを反復処理します。

于 2008-10-13T14:05:34.063 に答える