AffineTransformについて

広告

ではAffineTransformについて見てみましょう。AffineTransformクラスは下記のように定義されています。

  • java.lang.Object
  • java.awt.geom.AffineTransform
  • public class AffineTransform extends Object implements Cloneable, Serializable

コンストラクタは下記のようなものが用意されています。

コンストラクタ
AffineTransform()
恒等変換を表現する新しい AffineTransform を構築します。
AffineTransform(AffineTransform Tx)
指定された AffineTransform オブジェクトのコピーである、新しい AffineTransform を構築します。
AffineTransform(double[] flatmatrix)
3×3 変換行列の 4 つの非平行移動エントリまたは 6 つの指定可能エントリのどちらかを表現する倍精度値の配列から、新しい AffineTransform を構築します。
AffineTransform(double m00, double m10, double m01, double m11, double m02, double m12)
3×3 変換行列の 6 つの指定可能エントリを表現する 6 つの倍精度値から、新しい AffineTransform を構築します。
AffineTransform(float[] flatmatrix)
3×3 変換行列の 4 つの非平行移動エントリまたは 6 つの指定可能エントリのどちらかを表現する浮動小数点値の配列から、新しい AffineTransform を構築します。
AffineTransform(AffineTransform Tx)
指定された AffineTransform オブジェクトのコピーである、新しい AffineTransform を構築します。
AffineTransform(float m00, float m10, float m01, float m11, float m02, float m12)
3×3 変換行列の 6 つの指定可能エントリを表現する 6 つの浮動小数点値から、新しい AffineTransform を構築します。

AffineTransformは二次元の座標を他の二次元の座標に変換するのに用いられます。簡単な使い方は前のページで見た通りですがAffineTransformを使った変換方法についてもう少し細かく見てみます。

AffineTransformによる変換について

では実際にAffineTransformを使ってどのように変換しているのかを見てみましょう。例えば頂点(x, y)をAffineTransformを使って変換する場合、下記のような3×3の配列による変換をしています。

[ x']   [  m00  m01  m02  ] [ x ]   [ m00x + m01y + m02 ]
[ y'] = [  m10  m11  m12  ] [ y ] = [ m10x + m11y + m12 ]
[ 1 ]   [   0    0    1   ] [ 1 ]   [         1         ]

ここで元の座標(x, y)はAffineTransformを使って新しい座標(x', y')に変換されます。実際の値は、

x' = m00 * x + m01 * y + m02
y' = m10 * x + m11 * y + m12

となるわけです。

上記を見て頂くと分かる通り、m02とm12がX軸とY軸の平行移動する場合に関係する値です。
例えばX軸方向に4ピクセル移動させたいのであれば、物体の各頂点のX座標をそれぞれ"+ 4"すればいいので

 [ 1 0 4 ]    [ x ]   [ x' ]
 [ 0 1 0 ] × [ y ] = [ y' ]
 [ 0 0 1 ]    [ 1 ]   [ w' ]

x' = x + 4
y' = y

のような変換をすればいいことになります。

変換行列の値の取得

AffineTransformのgetMatrixメソッドを使って現在設定されている変換行列の値を取得することができます。

3×3 アフィン変換行列内の 6 つの指定可能な値を取り出し、倍精度値の配列
に配置します。各値は配列に { m00, m10, m01, m11, m02, m12 } という形式
で格納されます。
4 つの double 値の配列も指定できます。その場合は、配列の非平行移動部分
を表す最初の 4 つの要素だけが取り出され、値は配列に { m00, m10, m01, m11 } 
という形式で格納されます。

パラメータ:
  flatmatrix - 戻り値を格納するために使用する double 値の配列

ではデフォルトコンストラクタの場合の値を取り出してみましょう。

import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;

public class AffineTransformTest extends JPanel{
  public static void main(String[] args){
    JFrame frame = new JFrame();

    AffineTransformTest test = new AffineTransformTest();
     frame.getContentPane().add(test);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setBounds( 0, 0, 200, 200);
    frame.setVisible(true);

    double[] flatmatrix = new double[6];
    AffineTransform af = new AffineTransform();
    af.getMatrix(flatmatrix);

    printMatrix(flatmatrix);
  }

  public static void printMatrix(double[] flatmatrix){
    System.out.print("[ " + flatmatrix[0] + " ");
    System.out.print(flatmatrix[2] + " ");
    System.out.println(flatmatrix[4] + " ]");

    System.out.print("[ " + flatmatrix[1] + " ");
    System.out.print(flatmatrix[3] + " ");
    System.out.println(flatmatrix[5] + " ]");
  }
}

実行すると下記のように出力されます。

[ 1.0 0.0 0.0 ]
[ 0.0 1.0 0.0 ]

デフォルトでは単位行列になるようです。

では45度回転させた場合も見てみます。

import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;

public class AffineTransformTest extends JPanel{
  public static void main(String[] args){
    JFrame frame = new JFrame();

    AffineTransformTest test = new AffineTransformTest();
    frame.getContentPane().add(test);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setBounds( 0, 0, 200, 200);
    frame.setVisible(true);

    double[] flatmatrix = new double[6];
    AffineTransform af = new AffineTransform();
    af.rotate(45 * Math.PI / 180);

    af.getMatrix(flatmatrix);

    printMatrix(flatmatrix);
  }

  public static void printMatrix(double[] flatmatrix){
    System.out.print("[ " + flatmatrix[0] + " ");
    System.out.print(flatmatrix[2] + " ");
    System.out.println(flatmatrix[4] + " ]");

    System.out.print("[ " + flatmatrix[1] + " ");
    System.out.print(flatmatrix[3] + " ");
    System.out.println(flatmatrix[5] + " ]");
  }
}

実行すると下記のように出力されます。

[ 0.7071067811865476 -0.7071067811865475 0.0 ]
[ 0.7071067811865475  0.7071067811865476 0.0 ]

デフォルト以外のコンストラクタ

では他のコンストラクタも確認してみましょう。

3×3 変換行列の 6 つの指定可能エントリを表現する 6 つの倍精度値から、
新しい AffineTransform を構築します。 

パラメータ:
  m00, m01, m02, m10, m11, m12 - 3x3 変換行列を構成する 6 つの浮動小
    数点値

このコンストラクタを使用すると、

 [  m00  m01  m02  ] 
 [  m10  m11  m12  ] 
 [   0    0    1   ] 

のように値が設定されます。これも試してみましょう。

import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;

public class AffineTransformTest extends JPanel{
  public static void main(String[] args){
    JFrame frame = new JFrame();

    AffineTransformTest test = new AffineTransformTest();
    frame.getContentPane().add(test);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setBounds( 0, 0, 200, 200);
    frame.setVisible(true);

    double[] flatmatrix = new double[6];
    AffineTransform af = 
      new AffineTransform(0.1d, 0.2d, 0.3d, 0.4d, 0.5d, 0.6d);

    af.getMatrix(flatmatrix);

    printMatrix(flatmatrix);
  }

  public static void printMatrix(double[] flatmatrix){
    System.out.print("[ " + flatmatrix[0] + " ");
    System.out.print(flatmatrix[2] + " ");
    System.out.println(flatmatrix[4] + " ]");

    System.out.print("[ " + flatmatrix[1] + " ");
    System.out.print(flatmatrix[3] + " ");
    System.out.println(flatmatrix[5] + " ]");
  }
}

実行すると下記のように出力されます。

[ 0.1 0.3 0.5 ]
[ 0.2 0.4 0.6 ]

( Written by Tatsuo Ikura )