Javaプログラミング学習サイト ゆるゆるプログラミング

2019/09/14 公開

・グラフの描画

Swingパッケージを使って数式のグラフを表示する方法を解説します。

ここで扱う数式は、

  y = f(x)

と表すもので、xを与えてyを求める関数です。以下はその例です。

  y = |x| … 絶対値

  y = x * x … 放物線

  y = √x … 平方根

  y = sin(x) … サイン(正弦

  y = cos(x) … コサイン(余弦

  y = tan(x) … タンジェント(正接

以上が、xからyを求める関数の例です。

それでは、y = f(x)で表される関数をグラフ表示する方法について考えていきます。

まず、数学座標(x,f(x))をそのままグラフィック座標に当てはめることを考えます。下の図は、数学座標系グラフィック座標系(画像座標系)を表したものです。

数学座標系から画像座標系への変換 この図から、以下のような問題があることがわかります。

 ・上下反転する。

 ・マイナスの座標が表示できない。

 ・座標の範囲に限界がある。(0,0)-(幅ピクセル- 1,高さピクセル - 1)

 ・小数が取り扱えない。                      など

このため、数式の値で直接グラフを表示することはできません。

そこで、数学座標で指定した座標の範囲を、グラフィック座標に変換することでグラフを表示することを考えます。これには、数学座標の一部の範囲をグラフィック座標に変換する方法を使います。

数学座標と画像座標の対応

グラフィック座標は小数点が使えないので完全なグラフを表示することはできませんが、表示するグラフィック座標の縦横のピクセル数を多くすることでより正確なグラフを表現することができます。

下の図は、sinカーブの描画例で、横軸を角度(単位°)、縦軸をsin(角度)の値としたものです。

y=sin(x)をグラフ表示

sinカーブの描画は、以下のソースコードを参考にしてください。

また、xy座標からグラフィックの座標の変換のJavaソースコードはこちらを参照してください。「数学座標→画像座標変換」

コンパイルするときは、javacコマンドに"GR_SinCurve.java"と"Transformation2d.java"の2つのソースコードを指定してください。

GR_SinCurveのコンパイル

javac GR_SinCurve.java Transformation2d.java

GR_SinCurve.java ← クリックしてダウンロードページに移動
001:    import java.awt.*;
002:    import javax.swing.*;
003:    
004:    public class GR_SinCurve {
005:    	public static void main(String[] args) {
006:    		// フレームの大きさを設定
007:    		int w  = 400;
008:    		int h = 320;
009:    
010:    		// フレームを作成
011:    		JFrame frame = new JFrame();
012:    
013:    		// // タイトル名を設定
014:    		frame.setTitle( "サインカーブ" );
015:    
016:    
017:    		// 内側フレームの大きさを設定
018:    		frame.getContentPane().setPreferredSize( new Dimension( w, h ) );
019:    		frame.pack();
020:    
021:    		// ”×”ボタンを押した時の処理を設定
022:    		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
023:    
024:    		// フレームにパネルを追加
025:    		MyPanel panel = new MyPanel();
026:    		frame.getContentPane().add( panel );
027:    
028:    		// フレームを表示
029:    		frame.setVisible( true );
030:    	}
031:    }
032:    
033:    
034:    // JPanelを継承したMyPanelを作成
035:    class MyPanel extends JPanel {
036:    	public MyPanel() {
037:    		// 背景色を黒(black)に設定
038:    		setBackground( Color.white );
039:    	}
040:    
041:    	// 関数
042:    	private double f( double x )
043:    	{
044:    		// 角度degをラジアンradに変換
045:    		double rad = Math.toRadians( (double)x );
046:    		// サインを計算
047:    		return Math.sin( rad );
048:    	}
049:    
050:    
051:    	// ラインの開始座標
052:    	private int line_x1 = 0;
053:    	private int line_y1 = 0;
054:    
055:    	// ラインの開始座標の設定
056:    	private void moveTo(Graphics g, int x, int y )
057:    	{
058:    		line_x1 = x;
059:    		line_y1 = y;
060:    	}
061:    
062:    	// ラインの表示
063:    	private void lineTo(Graphics g, int x, int y )
064:    	{
065:    		g.drawLine( line_x1, line_y1, x, y );
066:    		line_x1 = x;
067:    		line_y1 = y;
068:    	}
069:    
070:    	// 描画
071:    	public void paintComponent( Graphics g ) {
072:    		super.paintComponent( g );
073:    
074:    		// フレームの大きさを取得
075:    		int frame_w = getWidth();
076:    		int frame_h = getHeight();
077:    
078:    		// 座標変換クラスの作成
079:    		Transformation2d trans = new Transformation2d();
080:    
081:    		// 座標を設定
082:    		// (-360.0,1.2)-(360.0,-1.2)の範囲がフレーム全体に表示する
083:    		trans.set( -360.0, 1.2, 360, -1.2, 0.0, 0.0,
084:    			(double)( frame_w - 1 ), (double)( frame_h - 1 ) );
085:    
086:    		// 原点の画像座標を取得
087:    		double origin_x = trans.getX( 0.0 );
088:    		double origin_y = trans.getY( 0.0 );
089:    
090:    		// 座標軸の色を黒
091:    		g.setColor( Color.black );
092:    
093:    		// x座標の描画
094:    		g.drawLine( 0, (int)origin_y, frame_w - 1, (int)origin_y );
095:    
096:    		// y座標の描画
097:    		g.drawLine( (int)origin_x, 0, (int)origin_x, frame_h - 1 );
098:    
099:    		// サイン(sin)カーブの描画
100:    		// サインカーブの色を赤
101:    		g.setColor( Color.red );
102:    
103:    		// 角度-360から360度までのサインカーブを表示
104:    		boolean isStart = true;
105:    		for ( int x = -360; x <= 360; x++ ) {
106:    			// 計算結果をyに代入
107:    			double y = f( x );
108:    
109:    			// 数学座標( deg, value )を
110:    			// 画像座標( line_x2, line_x2 )に変換
111:    			int px = (int)trans.getX( (double)x );
112:    			int py = (int)trans.getY( y );
113:    			
114:    			//
115:    			if ( true == isStart ) {
116:    				moveTo( g, px, py );
117:    				isStart = false;
118:    			}
119:    			else
120:    				lineTo( g, px, py );
121:    		}
122:    	}
123:    }

■関連コンテンツ

数学関数について 数学関数について解説
XY座標系 xとyで表す位置
画像の座標系 画像の座標系について解説
数学座標→画像座標変換 数学xy→画像xy
フレームの表示 図形を表示するフレーム(枠)の表示方法について解説
画素 画素について説明
画像処理とは 画像処理とは何かを解説
光と色の3原色の考え方を解説-画像

光と色の3原色

光の3色(RGB)の混合と、インクの3色(CMY)の混合の考え方を説明しています。

■新着情報

2021.09.24 配列の値が全て同じか? 全ての配列値の一致確認

■広告

 

 

 

 

 

スッキリわかるJava入門第3版 [ 中山清喬 ]

価格:2,860円
(2021/6/18 14:32時点)
感想(6件)

 

 

 

Topへ