2

アフィン変換用の JavaScript Matrix クラスと、特定の中心を中心に回転をラジアンの絶対数に設定する関数があります。

this.setRotation = function (radians, center) {
    var cos = Math.cos(radians);
    var sin = Math.sin(radians);
    this.a = cos;
    this.b = sin;
    this.c = -sin;
    this.d = cos;
    this.tx += center.x - center.x * cos + center.y * sin;
    this.ty += center.y - center.x * sin - center.y * cos;
}

オブジェクト自体の中心を中心に回転しようとしているので、オブジェクトの幅の半分、高さの半分の中心点を渡しているので、100 x 100 オブジェクトの場合は 50, 50 を渡しています。

私のオブジェクトがゼロの回転から始まる場合、これはうまくいきます:

前 後

...しかし、形状を再度回転させるか、ゼロ以外の回転から開始すると、tx と ty の値が間違ってしまいます。

位置が移動しました

上記の式の何が問題になっていますか? 回転の設定は正確に見えますが、tx と ty は正確ではありません。

この件に関する他のいくつかの質問、特にこの質問を見てきましたが、何も役に立ちませんでした。

更新これにいくつかの数字を追加するには:

100,100 に配置された 100x100 の長方形から始めると、最初の行列は次のようになります。{Matrix: [a:1, b:0, c:0, d:1, tx:100, ty:100]}

これを時計回りに 45 度回転させるには、上記の関数 0.7853981633974483 (ラジアンで 45 度) と中心をフィードします。{Point: [x:50, y: 50]}

これにより、次の行列が生成 されます。{Matrix: [a:0.7071067812, b:0.7071067812, c:-0.7071067812, d:0.7071067812, tx:150, ty:79.28932188]}これはまさに正しいものです。

{Point: [x:70.71067812000001, y: 70.71067812000001]}しかし、その行列から始めて、0 と(新しい回転した形状の中心) の関数引数を与えることによってそれをゼロに戻そうとすると、出力は{Matrix: [a:1, b:0, c:0, d:1, tx:150, ty:79.28932188]}になります。これは正しい回転ですが、正しい回転ではありません。翻訳。私は得ることを期待しています{Matrix: [a:1, b:0, c:0, d:1, tx:100, ty:100]}

50,50 のローカル センターの代わりに親座標空間 150,150 の長方形の中心を使用し、以下に提案するように += を = に置き換えるなど、関数の他のいくつかのバリエーションを試しましたが、何も役に立たないようです。tx 計算をコメントアウトすると、形状が原点を中心に美しく回転するため、問題は tx/ty 計算か、渡す中心点のいずれかにあるはずです。

他に何かアイデアはありますか?

4

2 に答える 2

1

おそらく間違った記号 (座標軸の方向によって異なります) は別として、問題は単に、アフィン行列のとの部分を埋めるときに+=代わりに使用していることだと思います。=txty

于 2012-09-26T12:00:26.247 に答える
0

私の問題は、オブジェクトを原点に戻すことでした-回転する前に左上の座標と高さと幅の半分を削除してから、それらを再度追加しました。

setRotate 関数よりも回転関数を使用する方が簡単であることがわかり、次のコードになりました。

// Matrix class functions:
this.rotate = function (radians) {
    var cos = parseFloat(Math.cos(radians).toFixed(10));
    var sin = parseFloat(Math.sin(radians).toFixed(10));
    a = this.a,
    b = this.b,
    c = this.c,
    d = this.d,
    tx = this.tx,
    ty = this.ty;
    this.a = a * cos - b * sin;
    this.b = a * sin + b * cos;
    this.c = c * cos - d * sin;
    this.d = c * sin + d * cos;
    this.tx = tx * cos - ty * sin;
    this.ty = tx * sin + ty * cos;
}

this.setRotation = function (radians) {
    var rotation = this.rotation();
    this.rotate(radians - rotation);
}

this.translate = function (tx, ty) {
    this.tx += tx;
    this.ty += ty;
}

// Called from outside the class
var transformedBounds = pe.Model.ReadTransformedBounds(selection[0]);
var itemTransform = pe.Model.ReadItemTransform(selection[0]);

// Cache the coordinates before translating them away:
var ox = transformedBounds.Left + (transformedBounds.Width / 2); 
var oy = transformedBounds.Top + (transformedBounds.Height / 2);
itemTransform.translate(-ox, -oy);

// Rotate:
itemTransform.setRotation(radians);

// Restore the translation:
itemTransform.translate(ox, oy);

あなたが実際に合計を計算できれば、これらすべてはおそらくかなり明白ですが、誰かが私のように暗い日を過ごした場合に備えて、ここに投稿します...

于 2012-09-26T17:50:13.437 に答える