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(角度)の値としたものです。

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色(RGB)の混合と、インクの3色(CMY)の混合の考え方を説明しています。 |
■新着情報
2021.12.21 | 現在の日時を取得 | いまの年月日、時分秒? |
■広告
