Java2Dでの図形の変形方法とは

広告

ここからは図形の変換について色々試してみます。

Java2Dで図形の移動や回転などを行うにはAffineTransformを使います。細かい説明は次のページから行いますので取り合えず簡単なサンプルを作ってみましょう。

Java2Dの座標系は左上が(0,0)の原点となっており、原点から右へ向かってX座標、原点から下に向かってY座標となっています。

座標系

まず下記のようなコードで長方形を書いてみます。

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

実行してみると下記のようになります。

平行移動

では平行移動させてみましょう。まずAffinTransformオブジェクトを作成し、AffinTransformクラスのsetToTranslationメソッドを使って平行移動させてみます。

AffineTransform af = new AffineTransform();
af.setToTranslation(30d, 60d);

どのように移動するを決定したら、それをセットします。セットするにはGraphics2DクラスのsetTransformメソッドを使います。

g2.setTransform(af);

では先ほどのサンプルを少し修正してみましょう。

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(30d, 60d);

    g2.setTransform(af);
    g2.setColor(Color.red);

    g2.draw(new Rectangle2D.Double(60, 20, 60, 40));
  }
}

実行してみると下記のようになります。

回転

次に回転を試してみます。AffinTransformオブジェクトに対して、AffinTransformクラスのrotatoメソッドを使ってどのくらい回転させるかを設定します。

AffineTransform af = new AffineTransform();
af.setToTranslation(30d, 60d);
af.rotate(45 * Math.PI / 180);

g2.setTransform(af);

上記の場合は、描画用座標に対してまず移動(setToTranslation)を行い、その後回転(rotato)をさせていることになります。

では先ほどのサンプルを少し修正してみましょう。

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(30d, 60d);
    af.rotate(45 * Math.PI / 180);

    g2.setTransform(af);
    g2.setColor(Color.red);

    g2.draw(new Rectangle2D.Double(60, 20, 60, 40));
  }
}

今度は移動したあと45度回転させた座標に長方形を描画しています。

実のところ、移動させたあとで回転させているのではなく、移動と回転を別々に計算してその合成した結果が表示されています。何故こうなるのかは次のページから詳しく説明したいと思います。

( Written by Tatsuo Ikura )