CGAffineTransformとCATransform3D(前編:CGAffineTransform)

iOSでは、平面図形の変換(平行移動、拡縮、回転)を行うためには、
CGAffineTransformを用いたアフィン変換を、
三次元における平面図形の変換には、CATransform3Dを使いますが、
CATransform3Dで少し詰まったことがあったので、基礎から理解しておこうと思い、
調べてみました。

前提

  • 行列計算の知識
  • 図形は点の集合であるという認識

幾何学的変換

移動

平面上の任意の点A(x,y)を考えます。 この時、点Aの座標を行列式で表すと、

{ \displaystyle
  A = \left[
    \begin{array}{cc}
      x\\
      y\\
    \end{array}
  \right]
}

これをx方向にtx、y方向にtyだけ移動した点A'の座標(x', y')は

{ \displaystyle
  \left[
    \begin{array}{cc}
      x'\\
      y'\\
    \end{array}
  \right]  = \left[
    \begin{array}{cc}
      x\\
      y\\
    \end{array}
  \right] +  \left[
    \begin{array}{cc}
    t_{ x}\\
    t_{ y}\\
    \end{array}
  \right]
}

図形は点の集合であるため、この処理によって図形上の全ての点がx方向にa、
y方向にb移動し、結果として図形がx方向にa、y方向にbだけ移動することとなります。

拡縮

移動の際と同様に、平面上の任意の点A(x,y)を考えます。 これをx方向にsx倍、
y方向にsy倍拡大(縮小)した点A''の座標(x''、y'')は

{ \displaystyle
  \left[
    \begin{array}{cc}
      x''\\
      y''\\
    \end{array}
  \right] = \left[
    \begin{array}{cc}
      s_{\ x}\ \ \ \ \ \  0\\
      0\ \ \ \ \ \ s_{\ y}\\
    \end{array}
  \right]
  \left[
    \begin{array}{cc}
      x\\
      y\\
    \end{array}
  \right] =
\left[
    \begin{array}{cc}
      s_{\ x}x\\
      s_{\ y}y\\
    \end{array}
  \right]
}

回転

平面上の任意の点A(x,y)は、原点を中心とする半径rの円上に位置する点と考えることができ、 この時、点AはX軸からφだけ回転したものと考えると、
点Aは以下のように考えることができます。

{ \displaystyle
  \left[
    \begin{array}{cc}
      x\\
      y\\
    \end{array}
  \right] = \left[
    \begin{array}{cc}
      rcosφ\\
      rsinφ\\
    \end{array}
  \right]
}

点Aをθだけ回転させて得られる点A'''(x''', y''')は

{ \displaystyle
  \left[
    \begin{array}{cc}
      x'''\\
      y'''\\
    \end{array}
  \right] = \left[
    \begin{array}{cc}
      rcos(φ+θ)\\
      rsin(φ+θ)\\
    \end{array}
  \right] = \left[
    \begin{array}{cc}
      rcosφcosθ - rsinφsinθ\\
      rsinφsinθ + rcosφcosθ\\
    \end{array}
  \right] = \left[
    \begin{array}{cc}
      xcosθ - ysinθ\\
      ysinθ + xcosθ\\
    \end{array}
  \right]
}

したがって、A'''の座標は以下の式で示すことができます。

{ \displaystyle
  \left[
    \begin{array}{cc}
      x'''\\
      y'''\\
    \end{array}
  \right] = \left[
    \begin{array}{cc}
      cosθ\ \ \ \ -sinθ\\
      cosθ\ \ \ \ \ \ \ sinθ\\
    \end{array}
  \right]
  \left[
    \begin{array}{cc}
      x\\
      y\\
    \end{array}
  \right]
}

アフィン変換

以上より、平面図形の平行移動、拡縮、回転を行う変換は、
次の数式で定義することができます。

{ \displaystyle
  \left[
    \begin{array}{cc}
      x'\\
      y'\\
    \end{array}
  \right] = \left[
    \begin{array}{cc}
      a\ \ \ \ \ \ b\\
      c\ \ \ \ \ \ d\\
    \end{array}
  \right]
  \left[
    \begin{array}{cc}
      x\\
      y\\
    \end{array}
  \right] + \left[
    \begin{array}{cc}
      t_{\ x}\\
      t_{\ y}\\
    \end{array}
  \right]
}

更に三次元の座標を導入すると、上記の式を以下のような式にまとめることができます。

{ \displaystyle
  \left[
    \begin{array}{ccc}
      x'\\
      y'\\
      1 \\
    \end{array}
  \right] = \left[
    \begin{array}{ccc}
      a\ \ \ \ \ \ b\ \ \ \ \ \ t_{\ x}\\
      c\ \ \ \ \ \ d\ \ \ \ \ \ t_{\ y}\\
      0\ \ \ \ \ \ 0\ \ \ \ \ \ 1\\
    \end{array}
  \right]
  \left[
    \begin{array}{ccc}
      x\\
      y\\
      1\\
    \end{array}
  \right]
}

CGAffineTransformMakeTranslationの場合は

{ \displaystyle
  \left[
    \begin{array}{ccc}
      x'\\
      y'\\
      1 \\
    \end{array}
  \right] = \left[
    \begin{array}{ccc}
      0\ \ \ \ \ \ 0\ \ \ \ \ \ t_{\ x}\\
      0\ \ \ \ \ \ 0\ \ \ \ \ \ t_{\ y}\\
      0\ \ \ \ \ \ 0\ \ \ \ \ \ 1\\
    \end{array}
  \right]
  \left[
    \begin{array}{ccc}
      x\\
      y\\
      1\\
    \end{array}
  \right]
}

CGAffineTransformMakeScaleの場合は

{ \displaystyle
  \left[
    \begin{array}{ccc}
      x'\\
      y'\\
      1 \\
    \end{array}
  \right] = \left[
    \begin{array}{ccc}
      s_{\ x}\ \ \ \ \ \ 0\ \ \ \ \ \ 0\\
      s_{\ y}\ \ \ \ \ \ 0\ \ \ \ \ \ 0\\
      0\ \ \ \ \ \ 0\ \ \ \ \ \ 1\\
    \end{array}
  \right]
  \left[
    \begin{array}{ccc}
      x\\
      y\\
      1\\
    \end{array}
  \right]
}

CGAffineTransformMakeRotationの場合は

{ \displaystyle
  \left[
    \begin{array}{ccc}
      x'\\
      y'\\
      1 \\
    \end{array}
  \right] = \left[
    \begin{array}{ccc}
      cosθ\ \ \ \ \ \ -sinθ\ \ \ \ \ \ 0\\
      cosθ\ \ \ \ \ \ sinθ\ \ \ \ \ \ \  \ 0\\
      0\ \ \ \ \ \ \ \ \ \ \ 0\ \ \ \ \ \ \ \ \ \ 1\\
    \end{array}
  \right]
  \left[
    \begin{array}{ccc}
      x\\
      y\\
      1\\
    \end{array}
  \right]
}

となります。

ここまでは、さほど苦労せずに理解できたと思います。
次回はこれを三次元に拡張したCATransform3Dについて
説明します。