実験室 |
グラフィックの座標系 AffineTransform |
||||||||||
AffineTransform とは |
||||||||||
Java 2 では AWT に加えて、JFC (Java Foundation Classes) が加わりました。JFC の中でも Swing が注目されがちですが、2 次元グラフィックスや印刷関連の API の大幅に拡充されました。 そこで、あまり日のあたることのない 2 次元グラフィックス API の Java2D を取り上げてみましょう。 なるべく、簡単な例でいろいろ試してみてみましょう。 まず第一弾として java.awt.geom.AffineTransform クラスを極めてみましょう。 Java 2D では、 2 つの座標系があります。1 つがデバイス空間、他方がユーザ空間です。デバイス空間は文字通りコンピュータで表示できる物理的な座標系です。VGA であれば 640 × 480 pixels の空間になります。 他方のユーザ空間はユーザが自由に決めることができる空間です。 この 2 つの座標系を結びつけるのが AffineTransform クラスです。ユーザはユーザ空間をデバイス空間というのぞき窓からのぞき見るような感じですね。このときにただのぞき見るのではなく、拡大や縮小、回転などを行ってしまうのが AffineTransform クラスです。
まあ、むずかしい話はここらへんにしておいて、AffineTransform クラスを使ってみましょう。 まず、基本となる Applet を作ってみました。単に 2 つの四角形を描く Applet です。Java 2 を使用しているので、Netscape 6 以外のブラウザーであれば Java Plug-in が必要です。
Java 2D で描画をするときも、今までと同じように paint メソッドで記述します。異なるのは paint メソッドの引数である Graphics オブジェクトを Graphics2D にキャストすることです。これだけで、Java 2D を使用することができます。Gaphics2D クラスは Graphics クラスの派生クラスなので、Graphics クラスの機能はすべて受けついでいます。 Graphics2D で描画を行うときは draw メソッドもしくは fill メソッドを使います。前者が単に描画を行い、後者は塗りつぶしを行います。 draw メソッド、fill メソッドとも引数は java.awt.Shape オブジェクトとなっています。Shape オブジェクトは幾何図形を表したインタフェースです。これをインプリメントしたものに長方形をあらわす java.awt.geom.Rectangle2D クラスなどがあります。 AffineTransformTest1.java では 2 つの長方形を描画しています。 まず、init メソッドで 2 つの長方形を生成します。
Rectangle2D クラスは精度の違いにより Rectangle2D.Double クラスと Rectangle2D.Floag クラスがありますが、ここでは Rectangle2D.Double クラスを使いました。コンストラクタの引数は始点の x 座標、y 座標、幅、高さです。 paint メソッドは単に rect1, rect2 を描画するだけです。
実行してみると、単に 2 つの四角形を描画するだけです。 デフォルト状態ではデバイス空間とユーザー空間は同一になっています。
|
回転 |
||||||||||||||||||||
まずは単純に AffineTransform クラスで座標系の変換をしてみましょう。ここでは座標軸を回転させてみます。
AffineTransorm クラスは普通にコンストラクタを使用して生成することもできますが、生成のための static メソッドも用意されています。今回はそれを使ってみました。AffintTransform
オブジェクトも四角形と同じように init メソッドで生成します。
この AffineTransform オブジェクトは (0, 0) を中心にして 45°の回転を行うものです。このほかにも次のような生成のためのメソッドがあります。
それでは描画してみましょう。座標変換を行うには Graphics2D#setTransform メソッドを使用します。
実行させるとどうなりましたか。長方形が回転して描画されているのが確認できたでしょうか。 ユーザ空間を回転させるということがどういうことかを図 2 で示してみました。
デバイス空間というのぞき窓の位置は変わらないため、ユーザ空間とデバイス空間が回転によってずれてしまうわけです。
|
複数のユーザ空間 |
|||||||
次は、複数のユーザ空間を設定できるかどうかについてです。前章と同様に回転変換で試してみます。
長方形 rect1 オブジェクトはデフォルトのユーザ空間、rect2 が回転変換をほどこされるユーザ空間に描画します。
これを実行すると、rect1 はそのまま描画され、rect2 は回転した形で描画されます。 ということは、次のようなことがいえます。
|
ユーザ空間にほどこされた変換をもとにもどす |
||||||||
座標変換されてしまったユーザ空間は元に戻せるかやってみましょう。
ユーザ空間を元に戻すには、g2D オブジェクトにセットされた AffineTransform オブジェクトをチャラにしてしまえばいいと考えられます。そこで、ためしに setTransform メソッドの引数に null を入れてみましょう。
これを実行すると、g2D.setTransform(null) のところで NullPointerException が発生してしまいました。 null がだめだとすると、なにもしない AffineTransform オブジェクトを引数にしてみましょう。
引数がないコンストラクタを使用して、AffineTransform オブジェクトを生成すると、なにも変換しないオブジェクトが生成されます。これを setTransform の引数にしてみました。 実行してみると、期待通りユーザ空間は元に戻りました。 これからは、次のようなことがわかりました。
|
AffineTransform を使わない座標変換 |
|||||||||||||||||||
Graphics2D クラスの API を見ていると、下に示したようなメソッドがあります。これらのメソッドを用いても座標変換ができそうです。
さっそく、試してみましょう。
これまで、AffineTransform オブジェクトを生成していましたが、直接 Graphics2D オブジェクトに対して回転変換をセットします。
したがって、次のようなことがわかりました。
(Apr. 2003) |
|