2023.01.24

数学グラフ

xy-座標を描画するクラスの作成

Graphicsオブジェクトにxy-座標とグリッドを描画するためのクラスを作成しました。

このクラスを使うと、数学座標(xy-座標)からグラフィック座標への座標変換を意識することなく数学グラフが描画できます。下図は、xy-座標の描画例です。

xy-座標描画例

用意したメソッドは以下のとおりです。

以下は、初期化のメソッド原点座標とグリッドを設定します。

Axis2D.initメソッド

public boolean init( int fw, int fh, int ox, int oy, int gx, int gy, double sx, double sy )
・描画するxy-座標の情報を設定します。

  パラメータ fw     : フレームの横のピクセル数
        fh     : フレームの縦のピクセル数
        ox     : グラフィック座標の原点xの位置(pixel) 
        oy     : グラフィック座標の原点yの位置(pixel) 
        gx     : グラフィック座標のグリッドの幅(pixel) 
        gy     : グラフィック座標のグリッドの高さ(pixel) 
        sx     : 数学座標のグリッドの幅(gxあたりの幅)
                       例)sx=1.0を指定した場合、数学座標でのグリッド幅は1.0になり、右方向が+(プラス)となります。
                       例)sx=-0.5を指定した場合、数学座標でのグリッド高は-0.5になり、右方向が-(マイナス)となります。
        sy     : 数学座標のグリッドの高さ(gyあたりの高さ)
                       例)sy=-1.0を指定した場合、数学座標でのグリッド幅は-1.0になり、上方向が+(プラス)となります。
                       例)sy=1.0を指定した場合、数学座標でのグリッド高は1.0になり、上方向が-(マイナス)となります。
                         グラフィック座標のY軸のプラス方向は下で、数学座標のY軸のプラス方向は上です。
                         このメソッドでは、syにマイナスを代入することで数学座標の上方向をプラスにしています。

  戻り値    true   : 設定に成功
         false  : 設定に失敗
XY座標描画の初期設定

以下は、設定した情報を元に、座標軸とグリッドを描画するメソッドです。

Axis2D.draw_gridメソッド

public void draw_grid( Graphics g, Color axiscolor, Color gridcolor )
・座標軸とグリッドを描画します。

  パラメータ g : 描画するGraphicsオブジェクト
        axiscolor : 座標軸の色
        gridcolor : グリッド(格子)の色

  戻り値   なし

  詳細     initメソッドで設定後に、このメソッドを呼ぶとGraphicsオブジェクトに座標とグリッドを描画します。座標軸とグリッドの線幅は1です。

以下は、数学座標に、塗りつぶし円を描画するメソッドです。

Axis2D.draw_fillcircleメソッド

public void draw_fillcircle( Graphics g, double x, double y, int radius, Color color )
・塗りつぶし円を描画します。

  パラメータ g : 描画するGraphicsオブジェクト
        x : 数学座標の円の中心座標x
        y : 数学座標の円の中心座標y
        radius : グラフィック座標の円の半径
        color : 色

  戻り値   なし

  詳細     initメソッドで設定後に、このメソッドを呼んでください。

以下は、数学座標に、線分を描画するメソッドです。

Axis2D.draw_lineメソッド

public void draw_line( Graphics g, double x1, double y1, double x2, double y2, Color color )
・線分を描画します。

  パラメータ g : 描画するGraphicsオブジェクト
        x1 : 数学座標の座標x1
        y1 : 数学座標の座標y1
        x2 : 数学座標の座標x2
        y2 : 数学座標の座標y2
        color : 色

  戻り値   なし

  詳細     initメソッドで設定後に、このメソッドを呼んでください。描画する線分の線幅は1です。

Javaのソースコード

xy-座標とグリッド(格子)をGraphicsオブジェクトに描画するクラスソースコードです。

このソースコードは、座標変換を行うための「Transformation2d.java」を使用しています。

Graphicsオブジェクトにxy-座標を描画するソース

Axis2D.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import java.awt.*;

public class Axis2D {
	private Transformation2d trans = new Transformation2d();	// 座標変換クラス
	private int frame_w, frame_h;		// フレームサイズ
	private int grid_x, grid_y;		// グラフィック座標のグリッドサイズ
	private int origin_x, origin_y;		// グラフィック座標の原点の位置
	private double scale_x, scale_y;	// 数学座標のグリッドのサイズ

	// 初期化
	//  fw : フレームの幅(pixel) 
	//  fh : フレームの高さ(pixel) 
	//  ox : グラフィック座標の原点xの位置(pixel) 
	//  oy : グラフィック座標の原点yの位置(pixel) 
	//  gx : グラフィック座標のグリッドの幅(pixel) 
	//  gy : グラフィック座標のグリッドの高さ(pixel) 
	//  sx : 数学座標のグリッドの幅
	//  sy : 数学座標のグリッドの高さ
	public boolean init( int fw, int fh, int ox, int oy, int gx, int gy, double sx, double sy )
	{
		// グラフィック座標のグリッドの大きさをチェック
		if ( 1 > gx ) return false;
		if ( 1 > gy ) return false;

		// 数学座標→グラフィック座標へ変換するオブジェクトtransを作成
		//   ( 0.0, 0.0 ) → ( ox, oy )、( sx, sy ) → ( ox + gx, oy + gy )となるようにパラメーターを指定
		if ( !trans.set( 0.0, 0.0, sx, sy, (double)ox, (double)oy, (double)( ox + gx ), (double)( oy + gy ) ) ) return false;

		// フレームサイズをメンバ変数に代入
		frame_w = fw;
		frame_h = fh;

		// グラフィックの原点座標をメンバ変数に代入
		origin_x = ox;
		origin_y = oy;

		// グラフィック座標のグリッドサイズをメンバ変数に代入
		grid_x = gx;
		grid_y = gy;

		// 数学座標のグリッドサイズをメンバ変数に代入
		scale_x = sx;
		scale_y = sy;

		return true;
	}


	// グリッドとxy座標軸を描画
	//  g : Graphics オブジェクト 
	//  axiscolor : 描画するxy座標軸の色
	//  gridcolor : 描画するグリッドの色
	public void draw_grid( Graphics g, Color axiscolor, Color gridcolor )
	{
		// 方眼線の色を設定
		g.setColor( gridcolor );

		// y軸より上のグリッド線(水平線)を描画
		for ( int y = origin_y - grid_y; y >= 0; y -= grid_y )
			g.drawLine( 0, y, frame_w - 1, y );

		// y軸より下のグリッド線(水平線)を描画
		for ( int y = origin_y + grid_y; y < frame_h; y += grid_y )
			g.drawLine( 0, y, frame_w - 1, y );

		// x軸より左のグリッド線(垂直線)を描画
		for ( int x = origin_x - grid_x; x >= 0; x -= grid_x )
			g.drawLine( x, 0, x, frame_h - 1 );

		// x軸より右のグリッド線(垂直線)を描画
		for ( int x = origin_x + grid_x; x < frame_w; x += grid_x )
			g.drawLine( x, 0, x, frame_h - 1 );

		// 座標軸の描画
		// 座標軸の色を設定
		g.setColor( axiscolor );

		// x軸の描画
		g.drawLine( 0, origin_y, frame_w - 1, origin_y );

		// y軸の描画
		g.drawLine( origin_x, 0, origin_x, frame_h - 1 );
	}


	// 塗りつぶし円の描画
	//  g : Graphics オブジェクト 
	//  x : 数学座標の円の中心座標x
	//  y : 数学座標の円の中心座標y
	//  radius : グラフィック座標の円の半径
	//  color : 色
	public void draw_fillcircle( Graphics g, double x, double y, int radius, Color col )
	{
		// グラフィック座標格納変数
		int vx, vy;

		// 色の設定
		g.setColor( col );

		// 数学座標からグラフィック座標へ変換
		vx = (int)( trans.getX( x ) - (double)radius );
		vy = (int)( trans.getY( y ) - (double)radius );

		// 塗りつぶし円の描画
		g.fillOval( vx, vy, radius * 2 + 1, radius * 2 + 1 ); 
	}


	// 線分の描画 線幅は1
	//  g : Graphics オブジェクト 
	//  x1 : 数学座標の座標x1
	//  y1 : 数学座標の座標y1
	//  x2 : 数学座標の座標x2
	//  y2 : 数学座標の座標y2
	//  color : 色
	public void draw_line( Graphics g, double x1, double y1, double x2, double y2, Color col )
	{
		// グラフィック座標格納変数
		int vx1, vy1;
		int vx2, vy2;

		// 色の設定
		g.setColor( col );

		// 数学座標からグラフィック座標へ変換
		vx1 = (int)trans.getX( x1 );
		vy1 = (int)trans.getY( y1 );
		vx2 = (int)trans.getX( x2 );
		vy2 = (int)trans.getY( y2 );

		// 線分の描画
		g.drawLine( vx1, vy1, vx2, vy2 ); 
	}
}

座標変換を行うソース

Transformation2d.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
public class Transformation2d {
	// 変換パラメータ a,b,c,d
	private double a = 0.0;
	private double b = 0.0;
	private double c = 0.0;
	private double d = 0.0;

	// パラメータを計算
	boolean set( double x1, double y1, double x2, double y2,
				double px1, double py1, double px2, double py2 )
	{
		// ゼロとみなす値
		double e = 0.0000000001;

		// 初期値を代入
		a = b = c = d = 0.0;

		// x1とx2が同じ値であればエラー
		if ( e > Math.abs( x1 - x2 ) ) return false;

		// y1とy2が同じ値であればエラー
		if ( e > Math.abs( y1 - y2 ) ) return false;

		// パラメータの計算
		a = ( px1 - px2 ) / ( x1 - x2 );
		b = ( px1 * x2 - px2 * x1 ) / ( x2 - x1 );
		c = ( py1 - py2 ) / ( y1 - y2 );
		d = ( py1 * y2 - py2 * y1 ) / ( y2 - y1 );

		return true;
	}


	// 変換後のx座標を取得
	public double getX( double x )
	{
		return a * x + b;
	}

	// 変換後のy座標を取得
	public double getY( double y )
	{
		return c * y + d;
	}
}

数学座標からグラフィック座標への変換方法については、こちらで詳しく解説しています。

数学座標(x,y)を画像座標(px,py)に変換する方法をソースコードを使って詳しく説明しています。

2020.03.23

Javaソースコードの解説

001
import java.awt.*;

Javaクラスライブラリの中から「java.awt」というパッケージにあるクラスを、このプログラム内で使うために記述します。

これで、Graphicsクラスが使用できるようになります。

003
public class Axis2D {

座標軸とグリッドを描画するAxis2Dクラスを定義しています。

004
	private Transformation2d trans = new Transformation2d();	// 座標変換クラス

数学座標からグラフィック座標に変換するTransformation2dクラスをインスタンス化しています。

005
	private int frame_w, frame_h;		// フレームサイズ

フレームの横のピクセル数を格納する変数frame_w、縦のピクセル数を格納する変数frame_hを宣言しています。

006
	private int grid_x, grid_y;		// グラフィック座標のグリッドサイズ

グラフィック座標のグリッドサイズを格納する変数grid_xとgrid_yを宣言しています。

007
	private int origin_x, origin_y;		// グラフィック座標の原点の位置

グラフィック座標原点座標を格納する変数origin_xとorigin_yを宣言しています。

008
	private double scale_x, scale_y;	// 数学座標のグリッドのサイズ

数学座標のグリッドサイズを格納する変数scale_xとscale_yを宣言しています。

010
011
012
013
014
015
016
017
018
019
020
	// 初期化
	//  fw : フレームの幅(pixel) 
	//  fh : フレームの高さ(pixel) 
	//  ox : グラフィック座標の原点xの位置(pixel) 
	//  oy : グラフィック座標の原点yの位置(pixel) 
	//  gx : グラフィック座標のグリッドの幅(pixel) 
	//  gy : グラフィック座標のグリッドの高さ(pixel) 
	//  sx : 数学座標のグリッドの幅
	//  sy : 数学座標のグリッドの高さ
	public boolean init( int fw, int fh, int ox, int oy, int gx, int gy, double sx, double sy )
	{

初期化するメソッドです。

021
022
023
		// グラフィック座標のグリッドの大きさをチェック
		if ( 1 > gx ) return false;
		if ( 1 > gy ) return false;

グラフィック座標のグリッドの大きさを格納している変数gxとgyが1未満かをif文で判定し、どちらかが1未満であればreturn文falseを戻し、メソッドを終了しています。

025
026
027
		// 数学座標→グラフィック座標へ変換するオブジェクトtransを作成
		//   ( 0.0, 0.0 ) → ( ox, oy )、( sx, sy ) → ( ox + gx, oy + gy )となるようにパラメーターを指定
		if ( !trans.set( 0.0, 0.0, sx, sy, (double)ox, (double)oy, (double)( ox + gx ), (double)( oy + gy ) ) ) return false;

座標変換するオブジェクトtransに、数学座標( 0.0, 0.0 )をグラフィック座標( ox, oy )に、数学座標( sx, sy )をグラフィック座標( ox + gx, oy + gy )に変換する引数を与えています。2次元座標系の場合は、変換前と変換後の座標の組み合わせが2つあれば、座標系全体の座標変換が行えます。

ここでは、グラフィック座標原点座標( ox, oy )と数学座標原点座標( 0.0, 0.0 )と、グラフィック座標の1グリッド先の座標( ox + gx, oy + gy )と数学座標のの1グリッド先の座標( 0.0 + sx, 0.0 + sy )の2つの組み合わせを使用しています。

029
030
031
		// フレームサイズをメンバ変数に代入
		frame_w = fw;
		frame_h = fh;

引数で渡されたフレームサイズをメンバ変数に格納しています。

033
034
035
		// グラフィックの原点座標をメンバ変数に代入
		origin_x = ox;
		origin_y = oy;

引数で渡されたグラフィック座標原点座標メンバ変数に格納しています。

037
038
039
		// グラフィック座標のグリッドサイズをメンバ変数に代入
		grid_x = gx;
		grid_y = gy;

引数で渡されたグラフィック座標のグリッドサイズをメンバ変数に格納しています。

041
042
043
		// 数学座標のグリッドサイズをメンバ変数に代入
		scale_x = sx;
		scale_y = sy;

引数で渡された数学座標のグリッドサイズをメンバ変数に格納しています。

049
050
051
052
053
054
	// グリッドとxy座標軸を描画
	//  g : Graphics オブジェクト 
	//  axiscolor : 描画するxy座標軸の色
	//  gridcolor : 描画するグリッドの色
	public void draw_grid( Graphics g, Color axiscolor, Color gridcolor )
	{

グリッドと座標軸を描画するメソッドです。

このメソッドの内部では、グリッドを先に表示し、その後に座標軸を描画しています。

055
056
		// 方眼線の色を設定
		g.setColor( gridcolor );

ここからグリッドの描画です。

メソッド引数で渡されたgridcolorをGraphics.setColorメソッドに渡してグリッドの線の色を設定しています。

Graphics.setColorメソッド

public abstract void setColor( Color c )
・このグラフィックスコンテキストの現在の色を、指定された色に設定します。

  パラメータ c : 色

  戻り値   なし
058
059
060
		// y軸より上のグリッド線(水平線)を描画
		for ( int y = origin_y - grid_y; y >= 0; y -= grid_y )
			g.drawLine( 0, y, frame_w - 1, y );

y軸より上のグリッド線を描画しています。

グラフィック座標原点座標origin_yからグリッドの高さgrid_yを引いた値origin_y - grid_yから間隔grid_yで上方向に水平のラインを描画していき、フレームの外に出れば描画を終了します。これをfor文繰り返し処理で行っています。

Graphics.drawLineメソッド

public abstract void drawLine( int x1, int y1, int x2, int y2 )
・このグラフィックスコンテキストの座標系の点 (x1, y1) と点 (x2, y2) との間に現在の色を使って線を描きます。

  パラメータ x1 : グラフィックスコンテキストのx座標1
        y1 : グラフィックスコンテキストのy座標1
        x2 : グラフィックスコンテキストのx座標2
        y2 : グラフィックスコンテキストのy座標2

  戻り値   なし
062
063
064
		// y軸より下のグリッド線(水平線)を描画
		for ( int y = origin_y + grid_y; y < frame_h; y += grid_y )
			g.drawLine( 0, y, frame_w - 1, y );

y軸より下のグリッド線を描画しています。

066
067
068
		// x軸より左のグリッド線(垂直線)を描画
		for ( int x = origin_x - grid_x; x >= 0; x -= grid_x )
			g.drawLine( x, 0, x, frame_h - 1 );

x軸より左のグリッド線を描画しています。

070
071
072
		// x軸より右のグリッド線(垂直線)を描画
		for ( int x = origin_x + grid_x; x < frame_w; x += grid_x )
			g.drawLine( x, 0, x, frame_h - 1 );

x軸より右グリッド線を描画しています。

074
075
076
		// 座標軸の描画
		// 座標軸の色を設定
		g.setColor( axiscolor );

ここから座標軸の描画です。

メソッド引数で渡されたaxiscolorをGraphics.setColorメソッドに渡して座標軸の色を設定しています。

078
079
		// x軸の描画
		g.drawLine( 0, origin_y, frame_w - 1, origin_y );

x軸を描画しています。

グラフィック座標原点座標origin_yを通り、フレームの左端(x=0)から右端(x=frame_w-1)までの水平線を描画しています。

081
082
		// y軸の描画
		g.drawLine( origin_x, 0, origin_x, frame_h - 1 );

y軸を描画しています。

グラフィック座標原点座標origin_xを通り、フレームの上端(y=0)から下端(y=frame_h-1)までの垂直線を描画しています。

086
087
088
089
090
091
092
093
	// 塗りつぶし円の描画
	//  g : Graphics オブジェクト 
	//  x : 数学座標の円の中心座標x
	//  y : 数学座標の円の中心座標y
	//  radius : グラフィック座標の円の半径
	//  color : 色
	public void draw_fillcircle( Graphics g, double x, double y, int radius, Color col )
	{

塗りつぶし円を描画するメソッドです。

094
095
		// グラフィック座標格納変数
		int vx, vy;

数学座標を変換したグラフィック座標を格納するint型変数vx、vyを宣言しています。

097
098
		// 色の設定
		g.setColor( col );

メソッド引数で渡されたcolをGraphics.setColorメソッドに渡して円の色を設定しています。

100
101
102
		// 数学座標からグラフィック座標へ変換
		vx = (int)( trans.getX( x ) - (double)radius );
		vy = (int)( trans.getY( y ) - (double)radius );

メソッド引数で渡された数学座標の円の中心座標(x,y)をtrans.getXメソッドtrans.getYメソッドで変換した値をから円の半径radiusを引いた値をvx、vyに代入しています。

変換した座標から半径radiusを引く理由は、塗りつぶし円を描画するdrawOvalメソッドに渡す座標が、描画する円の左上隅の座標であるためです。

円の中心座標を変換した座標をvxとvyに代入して半径radiusを引いた値をdrawOvalメソッドに渡してもほぼ同じ結果が得られます。

ちなみに、drawOvalは楕円を描画するメソッドですが、描画する幅と高さを同じにすれば円が描画できます。

Graphics.drawOvalメソッド

public abstract void drawOval( int x, int y, int width, int height )
・楕円の輪郭線を描きます。
  パラメータ x      : 描画する楕円の左上隅のx座標
        y      : 描画する楕円の左上隅のy座標
        width  : 描画する楕円の幅
        height : 描画する楕円の高さ

  戻り値   なし
104
105
		// 塗りつぶし円の描画
		g.fillOval( vx, vy, radius * 2 + 1, radius * 2 + 1 ); 

drawOvalメソッドに左隅の座標( vx, vy )、幅と高さに( radius * 2 + 1 )を渡して塗りつぶし円を描画しています。

この幅と高さの計算では厳密に半径radiusの円にはなりませんが、ここでは円の中心が真ん中になるように幅と高さを奇数にしています。

109
110
111
112
113
114
115
116
117
	// 線分の描画 線幅は1
	//  g : Graphics オブジェクト 
	//  x1 : 数学座標の座標x1
	//  y1 : 数学座標の座標y1
	//  x2 : 数学座標の座標x2
	//  y2 : 数学座標の座標y2
	//  color : 色
	public void draw_line( Graphics g, double x1, double y1, double x2, double y2, Color col )
	{

線分を描画するメソッドです。

118
119
120
		// グラフィック座標格納変数
		int vx1, vy1;
		int vx2, vy2;

線分の2つ数学座標を変換したグラフィック座標を格納するint型変数vx1、vy1、vx2、vy2を宣言しています。

122
123
		// 色の設定
		g.setColor( col );

メソッド引数で渡されたcolをGraphics.setColorメソッドに渡して線分の色を設定しています。

125
126
127
128
129
		// 数学座標からグラフィック座標へ変換
		vx1 = (int)trans.getX( x1 );
		vy1 = (int)trans.getY( y1 );
		vx2 = (int)trans.getX( x2 );
		vy2 = (int)trans.getY( y2 );

メソッド引数で渡された数学座標の線分の2つ座標( x1, y1 )、( x2, y2 )をtrans.getXメソッドtrans.getYメソッドで変換した値を( vx1, vy1 )、( vx2, vy2 )に格納しています。

131
132
		// 線分の描画
		g.drawLine( vx1, vy1, vx2, vy2 ); 

drawLineメソッドに2つの座標( vx1, vy1 )、( vx2, vy2 )を渡して線分を描画しています。

以上です。

関連コンテンツ

処理を繰り返すために使用するfor文について解説しています。

2020.03.23

Swingパッケージを使って数式のグラフを表示する方法を解説します。サイン(sin)カーブを表示するJavaソースコードを紹介しています。

2019.09.14

メソッドの定義方法を詳しく解説しています。Javaのサンプルソースコードを使った説明もあります。

2020.03.23

画像の座標系はどのように定義されていますか?

2020.03.23

平面上の位置を表す座標系の1つXY座標系について詳しく解説。

2020.03.23

Swingパッケージを使ってフレームを表示する方法を解説しています。

2020.03.23

広告