平行移動について

広告

先ほどのページでも少し書きましたが、例えばX軸方向に"+40"、Y軸方向に"+30"させたい場合には次のような変換行列を設定すればいいことになります。

 [ 1  0  40 ]    [ x ]   [ x' ]
 [ 0  1  30 ] × [ y ] = [ y' ]
 [ 0  0   1 ]    [ 1 ]   [ w' ]

x' = x + 40
y' = y + 30

このようにするにはコンストラクタで変換行列の値を渡してAffineTransformを作成するか、AffineTransformのsetTransformメソッドを使って変換行列を設定します。

この変換を 6 つの倍精度値によって指定されている行列に設定します。 

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

実際に簡単なサンプルを作成して試してみます。平行移動しつつ、変換行列の値を標準出力に出すようにします。

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);
  }

  public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.draw(new Rectangle2D.Double(60, 20, 60, 40));

    AffineTransform af = new AffineTransform();
    af.setTransform(1.0d, 0.0d, 0.0d, 1.0d, 40.0d, 30.0d);

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

    g2.setTransform(af);
    g2.setColor(Color.red);
    g2.draw(new Rectangle2D.Double(60, 20, 60, 40));
  }

  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 40.0 ]
[ 0.0 1.0 30.0 ]

setToTranslationメソッド

平行移動の場合には先ほどのように変換行列を自分で設定してもいいのですが、setToTranslationというメソッドが用意されているのでそれを使っても結構です。

この変換を平行移動変換に設定します。この変換を表現する行列は次のよう
になります。 
              [   1    0    tx  ]
              [   0    1    ty  ]
              [   0    0    1   ]

パラメータ:
  tx - 座標が X 軸方向で平行移動される距離
  ty - 座標が Y 軸方向で平行移動される距離

これは平行移動に特化したAffineTransformを作成したい時に便利です。注意点としては、元の行列にどのような値が設定されていた場合でも、上記の行列に置き換えられてしまうという点です。

では、これも簡単なサンプルで試してみます。

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);
  }

  public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.draw(new Rectangle2D.Double(60, 20, 60, 40));

    AffineTransform af = new AffineTransform();
    af.setToTranslation(40.0d, 30.0d);

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

    g2.setTransform(af);
    g2.setColor(Color.red);
    g2.draw(new Rectangle2D.Double(60, 20, 60, 40));
  }

  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 40.0 ]
[ 0.0 1.0 30.0 ]

translateメソッド

平行移動には実はもう1つメソッドがあります。translateメソッドを使っても平行移動が行えます。

この変換を平行移動変換に連結します。これは、concatenate(T) を呼び出す
ことに相当します。ただし、T は次の行列で表現される AffineTransform で
す。 

              [   1    0    tx  ]
              [   0    1    ty  ]
              [   0    0    1   ]

パラメータ:
  tx - 座標が X 軸方向で平行移動される距離
  ty - 座標が Y 軸方向で平行移動される距離

先ほどのsetToTranslationの場合は変換行列を完全に置き換えていましたが、translateの場合は置き換えではなく、既存の変換行列に新たに乗算を行い、その結果を新しい変換行列の値とします。

例えば既存の変換行列が下記左のような行列だった場合、trasnlateメソッドを実行することで、右の行列のような新しい変換行列になります。

 [ m00 m01 m02 ]    [ 1  0  tx ]    [ m00   m01   m00*tx + m01*ty + m02]
 [ m10 m11 m12 ] × [ 0  1  ty ] = [ m10   m11   m10*tx + m11*ty + m12]
 [ m20 m21 m22 ]    [ 0  0   1 ]    [ m20   m21   m20*tx + m21*ty + m22]

translateメソッドでは行列の右側の値以外は影響を受けません。平行移動に関する右側の値だけ上記のような値に変換します。これも簡単なサンプルで試して見ましょう。

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);
  }

  public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.draw(new Rectangle2D.Double(60, 20, 60, 40));

    AffineTransform af = new AffineTransform();
    af.setTransform(0.75d, 0.0d, 0.0d, 0.75d, 10.0d, 20.0d);

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

    System.out.println();

    af.translate(40.0d, 30.0d);

    af.getMatrix(flatmatrix);
    printMatrix(flatmatrix);

    g2.setTransform(af);
    g2.setColor(Color.red);
    g2.draw(new Rectangle2D.Double(60, 20, 60, 40));
  }

  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.75 0.0 10.0 ]
[ 0.0 0.75 20.0 ]

[ 0.75 0.0 40.0 ]
[ 0.0 0.75 42.5 ]

上が変換前の値で、下がtranslateした後の値です。ちなみに実行結果は下記のようになります。

今回の件とは関係ありませんが、単位行列の部分の値を変更することで、拡大や縮小ができます。

( Written by Tatsuo Ikura )