4

ポイントを中心にピースを回転できるhtml5キャンバスを使用して、マルチタッチジグソーパズルを書いています。各ピースには、境界ボックスのサイズの独自のキャンバスがあります。回転が発生すると、キャンバスのサイズを変更する必要があります。これは計算でき、機能しています。私が理解できないのは、これがピボット(最初のタッチポイント)を中心に回転しているように見える場合、新しい x、y オフセットを見つける方法です。

これは、私が達成しようとしていることをよりよく説明するための画像です。ピボット ポイントが常に中心であるとは限らないことに注意してください。それ以外の場合は、新しい境界と古い境界の差を半分にすることができます。

ここに画像の説明を入力

したがって、元の x、y、幅、高さ、回転角度、新しい境界 (rotatedWidth、rotatedHeight)、および元のオブジェクトに関連するピボット X、Y を知っています。取得方法がわからないのは、新しい境界の x/y オフセットです (オブジェクトがピボット ポイントを中心に回転したように見せるため)。

前もって感謝します!

4

2 に答える 2

8
  • まず、ピボット ポイントからコーナーまでの距離を見つける必要があります。
  • 次に、ピボットとコーナーの間の角度を計算します
  • 次に、前の角度 + 新しい角度に基づいて絶対角度を計算します。
  • そして最後に新しいコーナーを計算します。

デモからのスナップショット
ピボットからコーナーまでの線を示す下のデモのスナップショット。
平行移動を使用して四角形を回転させながら、赤い点が計算さ
れます。

ここでは絶対角度を使用した例を示しますが、これをたとえば新旧の角度の差の変換に簡単に変換できます。簡単にするために、角度をラジアンではなく度として保持しました。

デモでは、最初にキャンバスの内部移動と回転を使用して四角形を回転させます。次に、純粋な数学を使用して、コーナーの正しい新しい x 点と y 点を計算したという証拠と同じ点に到達します。

/// find distance from pivot to corner
diffX = rect[0] - mx; /// mx/my = center of rectangle (in demo of canvas)
diffY = rect[1] - my;
dist = Math.sqrt(diffX * diffX + diffY * diffY); /// Pythagoras

/// find angle from pivot to corner
ca = Math.atan2(diffY, diffX) * 180 / Math.PI; /// convert to degrees for demo

/// get new angle based on old + current delta angle
na = ((ca + angle) % 360) * Math.PI / 180; /// convert to radians for function

/// get new x and y and round it off to integer
x = (mx + dist * Math.cos(na) + 0.5)|0;
y = (my + dist * Math.sin(na) + 0.5)|0;

最初に、印刷された x と y が、長方形に対して定義された最初の角 (50、100) とまったく同じ値であることを確認することで確認できます。

アップデート

次の単語を見逃したようです:新しい境界のオフセット...申し訳ありませんが、代わりにできることは、代わりにコーナーまでの距離を計算することです。

これにより、境界の外側の制限が得られ、最小値と最大値を使用して、これらの距離値に基づいてコーナーベースを「混ぜ合わせる」だけです。

新しいライブデモはこちら

境界

新しい部分は、コーナーの x と y を与える関数で構成されています。

///mx, my = pivot, cx, cy = corner, angle in degrees
function getPoint(mx, my, cx, cy, angle) {

    var x, y, dist, diffX, diffY, ca, na;

    /// get distance from center to point
    diffX = cx - mx;
    diffY = cy - my;
    dist = Math.sqrt(diffX * diffX + diffY * diffY);
    
    /// find angle from pivot to corner
    ca = Math.atan2(diffY, diffX) * 180 / Math.PI;
  
    /// get new angle based on old + current delta angle
    na = ((ca + angle) % 360) * Math.PI / 180;
    
    /// get new x and y and round it off to integer
    x = (mx + dist * Math.cos(na) + 0.5)|0;
    y = (my + dist * Math.sin(na) + 0.5)|0;
    
    return {x:x, y:y};
}

これで、コーナーごとに関数を実行し、最小/最大を実行して境界を見つけるだけです。

/// offsets
c2 = getPoint(mx, my, rect[0], rect[1], angle);
c2 = getPoint(mx, my, rect[0] + rect[2], rect[1], angle);
c3 = getPoint(mx, my, rect[0] + rect[2], rect[1] + rect[3], angle);
c4 = getPoint(mx, my, rect[0], rect[1] + rect[3], angle);

/// bounds
bx1 = Math.min(c1.x, c2.x, c3.x, c4.x);
by1 = Math.min(c1.y, c2.y, c3.y, c4.y);
bx2 = Math.max(c1.x, c2.x, c3.x, c4.x);
by2 = Math.max(c1.y, c2.y, c3.y, c4.y);
于 2013-10-16T04:18:13.330 に答える