/********************************/
/* 伝達関数のゲインと位相の計算 */
/* coded by Y.Suganuma */
/********************************/
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.text.*;
public class Test {
public static void main (String[] args)
{
BodePlot bd = new BodePlot("ボード線図");
}
}
class BodePlot extends Frame implements ActionListener, TextListener
{
double fl, fu, si[][], bo[][];
int k, m[], n[], n_g = -1;
TextField fl_t, fu_t, k_t, n_g_t, ex[];
TextArea ta;
Button bt;
Coef bunsi[], bunbo[];
ScrollPane sp;
/******************/
/* コンストラクタ */
/******************/
BodePlot(String name)
{
// Frameクラスのコンストラクタ(Windowのタイトルを引き渡す)
super(name);
// Windowの大きさ
setSize(790, 590);
// レイアウト,背景色,フォント
setLayout(new BorderLayout(5, 10));
setBackground(new Color(225, 255, 225));
Font f = new Font("TimesRoman", Font.BOLD, 20);
setFont(f);
// 上のパネル
Panel pn1 = new Panel();
pn1.setLayout(new GridLayout(2, 1, 10, 10));
add(pn1, BorderLayout.NORTH);
Panel pn11 = new Panel();
pn1.add(pn11);
pn11.add(new Label("式の数(グラフの数)"));
n_g_t = new TextField(3);
n_g_t.addTextListener(this);
pn11.add(n_g_t);
pn11.add(new Label(" "));
bt = new Button("実行");
bt.setBackground(Color.pink);
bt.addActionListener(this);
pn11.add(bt);
Panel pn12 = new Panel();
pn1.add(pn12);
pn12.add(new Label("周波数下限"));
fl = 0.01;
fl_t = new TextField("0.01", 3);
fl_t.addTextListener(this);
pn12.add(fl_t);
pn12.add(new Label(" 周波数上限"));
fu = 100.0;
fu_t = new TextField("100", 3);
fu_t.addTextListener(this);
pn12.add(fu_t);
pn12.add(new Label(" データ数"));
k = 100;
k_t = new TextField("100", 3);
k_t.addTextListener(this);
pn12.add(k_t);
// 中央のパネル
sp = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
add(sp, BorderLayout.CENTER);
// 下のパネル
Panel pn6 = new Panel();
add(pn6, BorderLayout.SOUTH);
ta = new TextArea(5, 50);
pn6.add(ta);
// ウィンドウを表示
setVisible(true);
// イベントアダプタ
addWindowListener(new WinEnd());
}
/************/
/* log10(x) */
/************/
static double log10(double x)
{
return Math.log(x) / Math.log(10.0);
}
/****************************************/
/* 伝達関数のsにjωを代入した値の計算 */
/* ff : ω(周波数) */
/* m : 分子の次数 */
/* si : 分子多項式の係数 */
/* n : 分母の次数 */
/* bo : 分母多項式の係数 */
/* return : 結果 */
/****************************************/
static Complex G_s(double ff, int m, double si[], int n, double bo[])
{
Complex f, x, y;
// 周波数を複素数に変換
f = new Complex (0.0, ff);
// 分子
x = value(f, m, si);
// 分母
y = value(f, n, bo);
return Complex.dev(x, y);
}
/**************************************/
/* 多項式のsにjωを代入した値の計算 */
/* f : jω(周波数,複素数) */
/* n : 多項式の次数 */
/* a : 多項式の係数 */
/* return : 結果 */
/**************************************/
static Complex value(Complex f, int n, double a[])
{
int i1, k1;
Complex x;
x = new Complex (0.0, 0.0);
for (i1 = 0; i1 <= n; i1++)
x = Complex.add(x, Complex.mul(new Complex(a[i1]), Complex.pow(f, i1)));
return x;
}
/******************************/
/* 上,左,下,右の余白の設定 */
/******************************/
public Insets getInsets()
{
return new Insets(70, 20, 20, 20);
}
/******************************/
/* ボタンが押されたときの処理 */
/******************************/
public void actionPerformed(ActionEvent e)
{
double x, h, f, ff, g_min, g_max, p_min, p_max, uc = 90.0 / Math.asin(1.0);
int i1, i2, k1, p, sw = 0;
String g_title[] = null;
Complex g;
ta.setForeground(Color.black);
ta.setText("");
// エラーの判定
if (n_g < 0) {
sw = 1;
ta.setForeground(Color.red);
ta.append(" 式の数を入力してください\n");
}
else {
g_title = new String [n_g];
for (i1 = 0; i1 < n_g; i1++) {
if (ex[i1].getText().length() <= 0) {
sw = 1;
ta.setForeground(Color.red);
ta.append(" " + (i1+1) + " 番目の式の説明(凡例)を入力してください\n");
}
else
g_title[i1] = ex[i1].getText();
}
for (i1 = 0; i1 < n_g; i1++) {
if (m[i1] < 0) {
sw = 1;
ta.setForeground(Color.red);
ta.append(" " + (i1+1) + " 番目の式の分子の次数を入力してください\n");
}
else {
for (i2 = 0; i2 <= m[i1]; i2++) {
if (bunsi[i1].bun_t[i2].getText().length() <= 0) {
sw = 1;
ta.setForeground(Color.red);
ta.append(" " + (i1+1) + " 番目の式の分子の s の " + i2 + " 次の係数を入力してください\n");
}
else
si[i1][i2] = Double.parseDouble(bunsi[i1].bun_t[i2].getText());
}
}
}
for (i1 = 0; i1 < n_g; i1++) {
if (n[i1] < 0) {
sw = 1;
ta.setForeground(Color.red);
ta.append(" " + (i1+1) + " 番目の式の分母の次数を入力してください\n");
}
else {
for (i2 = 0; i2 <= n[i1]; i2++) {
if (bunbo[i1].bun_t[i2].getText().length() <= 0) {
sw = 1;
ta.setForeground(Color.red);
ta.append(" " + (i1+1) + " 番目の式の分母の s の " + i2 + " 次の係数を入力してください\n");
}
else
bo[i1][i2] = Double.parseDouble(bunbo[i1].bun_t[i2].getText());
}
}
}
}
// ゲインと位相の計算
if (sw == 0) {
// 下限と上限の再設定
if (fl < 1.0) {
x = 0.1;
while (fl < x-1.0e-10)
x /= 10.0;
fl = x;
}
else {
x = 1.0;
while (fl > x-1.0e-10)
x *= 10.0;
fl = x;
}
if (fu < 1.0) {
x = 0.1;
while (fu < x+1.0e-10)
x /= 10.0;
fu = 10.0 * x;
}
else {
x = 1.0;
while (fu > x+1.0e-10)
x *= 10.0;
fu = x;
}
// 初期設定
double freq1[][] = new double [n_g][k+1];
double freq2[][] = new double [n_g][k+1];
double gain[][] = new double [n_g][k+1];
double phase[][] = new double [n_g][k+1];
h = (log10(fu) - log10(fl)) / k;
g_min = 0.0;
g_max = 0.0;
p_min = 0.0;
p_max = 0.0;
ta.setText(" 角周波数 ゲイン(dB) 位相(度)\n");
for (i1 = 0; i1 < n_g; i1++) {
ff = log10(fl);
ta.append(g_title[i1] + "\n");
for (i2 = 0; i2 <= k; i2++) {
// 周波数の対数を元に戻す
f = Math.pow(10.0, ff);
freq1[i1][i2] = f;
freq2[i1][i2] = f;
ta.append(" " + f);
// 値の計算
g = G_s(f, m[i1], si[i1], n[i1], bo[i1]);
// ゲインと位相の計算
gain[i1][i2] = 20.0 * log10(Complex.abs(g));
ta.append(" " + gain[i1][i2]);
if (i1 == 0 && i2 == 0) {
g_min = gain[i1][i2];
g_max = gain[i1][i2];
}
else {
if (gain[i1][i2] > g_max)
g_max = gain[i1][i2];
else if (gain[i1][i2] < g_min)
g_min = gain[i1][i2];
}
x = Complex.angle(g) * uc;
if (i2 > 0) {
while (Math.abs(phase[i1][i2-1]-x) > 180.0) {
if (x-phase[i1][i2-1] > 180.0)
x -= 360.0;
else {
if (x-phase[i1][i2-1] < -180.0)
x += 360.0;
}
}
}
phase[i1][i2] = x;
ta.append(" " + x + "\n");
if (i1 == 0 && i2 == 0) {
p_min = phase[i1][i2];
p_max = phase[i1][i2];
}
else {
if (phase[i1][i2] > p_max)
p_max = phase[i1][i2];
else if (phase[i1][i2] < p_min)
p_min = phase[i1][i2];
}
// 次の周波数
ff += h;
}
}
// グラフの描画
// グラフ,x軸,及び,y軸のタイトル
String title1[] = new String [3];
title1[0] = "ゲイン線図";
title1[1] = "角周波数";
title1[2] = "ゲイン(dB)";
// ゲイン線図
// x軸目盛り
double x_scale1[] = new double[3];
x_scale1[0] = fl; // 最小値
x_scale1[1] = fu; // 最大値
x_scale1[2] = 1.0; // 最大値
// y軸目盛り
double y_scale1[] = new double[3];
if ((g_max-g_min) < 1.0e-5) {
if (g_min > 0.0) {
k1 = (int)Math.round(g_min / 20);
y_scale1[0] = 20.0 * k1 - 20.0; // 最小値
y_scale1[1] = 20.0 * k1 + 20.0; // 最大値
}
else {
k1 = (int)Math.round(-g_min / 20);
y_scale1[0] = -20.0 * k1 - 20.0; // 最小値
y_scale1[1] = -20.0 * k1 + 20.0; // 最大値
}
}
else {
if (g_min > 0.0) {
k1 = (int)(g_min / 20);
y_scale1[0] = 20.0 * k1; // 最小値
}
else {
k1 = (int)(-g_min / 20);
if (Math.abs(-20.0*k1-g_min) > 1.0e-5)
k1++;
y_scale1[0] = -20.0 * k1; // 最小値
}
if (g_max > 0.0) {
k1 = (int)(g_max / 20);
if (Math.abs(20.0*k1-g_max) > 1.0e-5)
k1++;
y_scale1[1] = 20.0 * k1; // 最大値
}
else {
k1 = (int)(-g_max / 20);
y_scale1[1] = -20.0 * k1; // 最大値
}
}
y_scale1[2] = 20.0; // 刻み幅
// x軸の小数点以下桁数
p = 0;
if (fl < 1.0) {
p = 1;
x = 0.1;
while (fl < x-1.0e-10) {
x /= 10.0;
p++;
}
}
Bode gp1 = new Bode(title1, g_title, x_scale1, p, y_scale1, 0, freq1, gain, true, true);
// 位相線図
// グラフ,x軸,及び,y軸のタイトル
String title2[] = new String [3];
title2[0] = "位相線図";
title2[1] = "角周波数";
title2[2] = "位相(度)";
// x軸目盛り
double x_scale2[] = new double[3];
x_scale2[0] = fl; // 最小値
x_scale2[1] = fu; // 最大値
x_scale2[2] = 1.0; // 最大値
// y軸目盛り
double y_scale2[] = new double[3];
if ((p_max-p_min) < 1.0e-5) {
if (p_min > 0.0) {
k1 = (int)Math.round(p_min / 90);
y_scale2[0] = 90.0 * k1 - 90.0; // 最小値
y_scale2[1] = 90.0 * k1 + 90.0; // 最大値
}
else {
k1 = (int)Math.round(-p_min / 90);
y_scale2[0] = -90.0 * k1 - 90.0; // 最小値
y_scale2[1] = -90.0 * k1 + 90.0; // 最大値
}
}
else {
if (p_min > 0.0) {
k1 = (int)(p_min / 90);
y_scale2[0] = 90.0 * k1; // 最小値
}
else {
k1 = (int)(-p_min / 90);
if (Math.abs(-90.0*k1-p_min) > 1.0e-5)
k1++;
y_scale2[0] = -90.0 * k1; // 最小値
}
if (p_max > 0.0) {
k1 = (int)(p_max / 90);
if (Math.abs(90.0*k1-p_max) > 1.0e-5)
k1++;
y_scale2[1] = 90.0 * k1; // 最大値
}
else {
k1 = (int)(-p_max / 90);
y_scale2[1] = -90.0 * k1; // 最大値
}
}
y_scale2[2] = 90.0; // 刻み幅
Bode gp2 = new Bode(title2, g_title, x_scale2, p, y_scale2, 0, freq2, phase, true, true);
}
}
/************************************/
/* パラメータが変更されたときの処理 */
/************************************/
public void textValueChanged(TextEvent e)
{
int i1;
try {
if (e.getSource() == n_g_t) {
n_g = Integer.parseInt(n_g_t.getText());
ta.setForeground(Color.black);
ta.setText("");
if (n_g <= 0) {
ta.setForeground(Color.red);
ta.setText(" 0 より大きい数値を入力してください");
}
else {
si = new double [n_g][];
bo = new double [n_g][];
m = new int [n_g];
n = new int [n_g];
for (i1 = 0; i1 < n_g; i1++) {
m[i1] = -1;
n[i1] = -1;
}
remove(sp);
sp = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
add(sp, BorderLayout.CENTER);
Panel pn2 = new Panel();
pn2.setLayout(new GridLayout(n_g, 1, 10, 10));
sp.add(pn2);
ScrollPane sp1[] = new ScrollPane [n_g];
ScrollPane sp2[] = new ScrollPane [n_g];
Panel pn3[] = new Panel [n_g];
Panel pn4[] = new Panel [n_g];
Panel pn5[] = new Panel [n_g];
ex = new TextField [n_g];
bunsi = new Coef [n_g];
bunbo = new Coef [n_g];
for (i1 = 0; i1 < n_g; i1++) {
pn3[i1] = new Panel();
pn3[i1].setBackground(new Color(255, 255, 225));
pn3[i1].setLayout(new BorderLayout(5, 10));
pn2.add(pn3[i1]);
pn4[i1] = new Panel();
pn4[i1].add(new Label((i1+1) + "番目の式の説明:"));
ex[i1] = new TextField(10);
pn4[i1].add(ex[i1]);
pn3[i1].add(pn4[i1], BorderLayout.NORTH);
pn5[i1] = new Panel();
pn5[i1].setLayout(new GridLayout(1, 2, 10, 10));
pn3[i1].add(pn5[i1], BorderLayout.CENTER);
sp1[i1] = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
pn5[i1].add(sp1[i1]);
bunsi[i1] = new Coef(0, this, i1);
sp1[i1].add(bunsi[i1]);
sp2[i1] = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
pn5[i1].add(sp2[i1]);
bunbo[i1] = new Coef(1, this, i1);
sp2[i1].add(bunbo[i1]);
}
validate();
}
}
else if (e.getSource() == fl_t) {
fl = Double.parseDouble(fl_t.getText());
fu = Double.parseDouble(fu_t.getText());
ta.setForeground(Color.black);
ta.setText("");
if (fl <= 0.0) {
ta.setForeground(Color.red);
ta.setText(" 0 より大きい数値を入力してください");
}
else if (fu <= fl) {
ta.setForeground(Color.red);
ta.setText(" 上限より小さい数値を入力してください");
}
}
else if (e.getSource() == fu_t) {
fl = Double.parseDouble(fl_t.getText());
fu = Double.parseDouble(fu_t.getText());
ta.setForeground(Color.black);
ta.setText("");
if (fu <= 0.0) {
ta.setForeground(Color.red);
ta.setText(" 0 より大きい数値を入力してください");
}
else if (fu <= fl) {
ta.setForeground(Color.red);
ta.setText(" 下限より大きい数値を入力してください");
}
}
else if (e.getSource() == k_t) {
k = Integer.parseInt(k_t.getText());
ta.setForeground(Color.black);
ta.setText("");
if (k <= 0) {
ta.setForeground(Color.red);
ta.setText(" 0 より大きい数値を入力してください");
}
}
}
catch (NumberFormatException em) {}
}
/************/
/* 終了処理 */
/************/
class WinEnd extends WindowAdapter
{
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
}
/****************************/
/* ボード線図の描画 */
/* coded by Y.Suganuma */
/****************************/
class Bode extends Frame {
String title[]; // グラフのタイトル
String g_title[]; // 凡例(グラフの内容)
double xx_scale[]; // y軸目盛り
double x_scale[]; // 元のy軸目盛り
double y_scale[]; // y軸目盛り
double data_x[][]; // 元のデータ
double data_xx[][], data_y[][]; // データ
boolean d_t; // タイトル表示の有無
boolean d_g; // 凡例表示の有無
boolean log_c = false; // 対数に変換したか否か
int place_x; // 小数点以下の桁数(x軸)
int place_y; // 小数点以下の桁数(y軸)
int width = 900, height = 600; // Windowの大きさ(初期サイズ)
int bx1, bx2, by1, by2; // 表示切り替えボタンの位置
String change = " 色 "; // 表示切り替えボタン
float line_w = 1.0f; // 折れ線グラフ等の線の太さ
Color cl[] = {Color.black, Color.magenta, Color.blue, Color.orange, Color.cyan,
Color.pink, Color.green, Color.yellow, Color.darkGray, Color.red}; // グラフの色
int n_g; // グラフの数
/*********************************************************/
/* コンストラクタ */
/* title_i : グラフ,x軸,及び,y軸のタイトル */
/* g_title_i : 凡例 */
/* x_scale_i : データの最小値,最大値,目盛幅(y) */
/* place_x_i : 小数点以下の桁数(x軸) */
/* y_scale_i : データの最小値,最大値,目盛幅(y) */
/* place_y_i : 小数点以下の桁数(y軸) */
/* data_x_i : グラフのデータ(x軸) */
/* data_y_i : グラフのデータ(y軸) */
/* d_t_i : タイトル表示の有無 */
/* d_g_i : 凡例表示の有無 */
/*********************************************************/
Bode(String title_i[], String g_title_i[], double x_scale_i[],
int place_x_i, double y_scale_i[], int place_y_i,
double data_x_i[][], double data_y_i[][], boolean d_t_i,
boolean d_g_i)
{
// Frameクラスのコンストラクタの呼び出し
super("ボード線図");
// テーブルデータの保存
title = title_i;
g_title = g_title_i;
x_scale = x_scale_i;
place_x = place_x_i;
y_scale = y_scale_i;
place_y = place_y_i;
data_x = data_x_i;
data_y = data_y_i;
d_t = d_t_i;
d_g = d_g_i;
int i1, i2;
int n_g = g_title.length;
int n_p = data_x[0].length;
xx_scale = new double [3];
data_xx = new double [n_g][n_p];
xx_scale[0] = x_scale[0];
xx_scale[1] = x_scale[1];
for (i1 = 0; i1 < n_g; i1++) {
for (i2 = 0; i2 < n_p; i2++)
data_xx[i1][i2] = data_x[i1][i2];
}
// Windowサイズと表示位置を設定
setSize(width, height);
Toolkit tool = getToolkit();
Dimension d = tool.getScreenSize();
setLocation(d.width / 2 - width / 2, d.height / 2 - height / 2);
// ウィンドウを表示
setVisible(true);
// イベントアダプタ
addWindowListener(new WinEnd());
addComponentListener(new ComponentResize());
addMouseListener(new ClickMouse(this));
}
/********/
/* 描画 */
/********/
public void paint (Graphics g)
{
double r, x1, y1, y2, sp, x_scale_org = 0.0;
int i1, i2, cr, k, k_x, k_y, k1, k2, kx, kx1, ky, ky1, han, len;
int x_l, x_r, y_u, y_d; // 描画領域
int f_size; // フォントサイズ
int n_p; // データの数
String s1;
Font f;
FontMetrics fm;
Graphics2D g2 = (Graphics2D)g;
//
// Windowサイズの取得
//
Insets insets = getInsets();
Dimension d = getSize();
width = d.width - (insets.left + insets.right);
height = d.height - (insets.top + insets.bottom);
x_l = insets.left + 10;
x_r = d.width - insets.right - 10;
y_u = insets.top + 20;
y_d = d.height - insets.bottom;
//
// グラフタイトルの表示
//
r = 0.05; // タイトル領域の割合
f_size = ((y_d - y_u) < (x_r - x_l)) ? (int)((y_d - y_u) * r) : (int)((x_r - x_l) * r);
if (f_size < 5)
f_size = 5;
if (d_t) {
f = new Font("TimesRoman", Font.BOLD, f_size);
g.setFont(f);
fm = g.getFontMetrics(f);
len = fm.stringWidth(title[0]);
g.drawString(title[0], (x_l+x_r)/2-len/2, y_d-f_size/2);
y_d -= f_size;
}
//
// 表示切り替えボタンの設置
//
f_size = (int)(0.8 * f_size);
if (f_size < 5)
f_size = 5;
f = new Font("TimesRoman", Font.PLAIN, f_size);
fm = g.getFontMetrics(f);
g.setFont(f);
g.setColor(Color.yellow);
len = fm.stringWidth(change);
bx1 = x_r - len - 7 * f_size / 10;
by1 = y_u - f_size / 2;
bx2 = bx1 + len + f_size / 2;
by2 = by1 + 6 * f_size / 5;
g.fill3DRect(bx1, by1, len+f_size/2, 6*f_size/5, true);
g.setColor(Color.black);
g.drawString(change, x_r-len-f_size/2, y_u+f_size/2);
//
// 凡例の表示
//
n_g = g_title.length;
if (d_g) {
han = 0;
for (i1 = 0; i1 < n_g; i1++) {
len = fm.stringWidth(g_title[i1]);
if (len > han)
han = len;
}
han += 15;
r = 0.2; // 凡例領域の割合
k1 = (int)((x_r - x_l) * r);
if (han > k1)
han = k1;
kx = x_r - han;
ky = y_u + 3 * f_size / 2;
k = 0;
g2.setStroke(new BasicStroke(7.0f));
for (i1 = 0; i1 < n_g; i1++) {
g.setColor(cl[k]);
g.drawLine(kx, ky, kx+10, ky);
g.setColor(Color.black);
g.drawString(g_title[i1], kx+15, ky+2*f_size/5);
k++;
if (k >= cl.length)
k = 0;
ky += f_size;
}
g2.setStroke(new BasicStroke(1.0f));
x_r -= (han + 10);
}
else
x_r -= (int)(0.03 * (x_r - x_l));
//
// x軸の対数
//
n_p = data_x[0].length;
x_scale_org = x_scale[0];
xx_scale[0] = Math.log(x_scale[0]) / Math.log(10.0);
xx_scale[1] = Math.log(x_scale[1]) / Math.log(10.0);
xx_scale[2] = 1.0;
for (i1 = 0; i1 < n_g; i1++) {
for (i2 = 0; i2 < n_p; i2++)
data_xx[i1][i2] = Math.log(data_x[i1][i2]) / Math.log(10.0);
}
//
// x軸及びy軸のタイトルの表示
//
if (title[1].length() > 0 && !title[1].equals("-")) {
len = fm.stringWidth(title[1]);
g.drawString(title[1], (x_l+x_r)/2-len/2, y_d-4*f_size/5);
y_d -= 7 * f_size / 4;
}
else
y_d -= f_size / 2;
if (title[2].length() > 0 && !title[2].equals("-")) {
g.drawString(title[2], x_l, y_u+f_size/2);
y_u += f_size;
}
//
// x軸,y軸,及び,各軸の目盛り
//
f_size = (int)(0.8 * f_size);
if (f_size < 5)
f_size = 5;
f = new Font("TimesRoman", Font.PLAIN, f_size);
fm = g.getFontMetrics(f);
y_d -= 3 * f_size / 2;
k_y = (int)((y_scale[1] - y_scale[0]) / (0.99 * y_scale[2]));
k_x = (int)((xx_scale[1] - xx_scale[0]) / (0.99 * xx_scale[2]));
g.setFont(f);
DecimalFormat df_x, df_y;
df_x = new DecimalFormat("#");
df_y = new DecimalFormat("#");
if (place_x != 0) {
s1 = "0.";
for (i1 = 0; i1 < place_x; i1++)
s1 += "0";
df_x = new DecimalFormat(s1);
}
if (place_y != 0) {
s1 = "#.";
for (i1 = 0; i1 < place_y; i1++)
s1 += "0";
df_y = new DecimalFormat(s1);
}
// y軸
y1 = y_scale[0];
len = 0;
for (i1 = 0; i1 < k_y+1; i1++) {
s1 = df_y.format(y1);
k1 = fm.stringWidth(s1);
if (k1 > len)
len = k1;
y1 += y_scale[2];
}
g.drawLine(x_l+len+5, y_u, x_l+len+5, y_d);
g.drawLine(x_r, y_u, x_r, y_d);
y1 = y_scale[0];
x1 = y_d;
sp = (double)(y_d - y_u) / k_y;
for (i1 = 0; i1 < k_y+1; i1++) {
ky = (int)Math.round(x1);
s1 = df_y.format(y1);
k1 = fm.stringWidth(s1);
g.drawString(s1, x_l+len-k1, ky+f_size/2);
g.drawLine(x_l+len+5, ky, x_r, ky);
y1 += y_scale[2];
x1 -= sp;
}
x_l += (len + 5);
// x軸
x1 = x_scale_org;
y1 = x_l;
sp = (double)(x_r - x_l) / k_x;
for (i1 = 0; i1 < k_x+1; i1++) {
kx = (int)Math.round(y1);
s1 = df_x.format(x1);
k1 = fm.stringWidth(s1);
g.drawString(s1, kx-k1/2, y_d+6*f_size/5);
g.drawLine(kx, y_d, kx, y_u);
if (i1 != k_x) {
g.setColor(Color.darkGray);
for (i2 = 2; i2 <= 9; i2++) {
y2 = Math.log(x1 * i2) / Math.log(10.0);
kx = x_l + (int)Math.round(((x_r - x_l) * (y2 - xx_scale[0]) / (xx_scale[1] - xx_scale[0])));
g.drawLine(kx, y_d, kx, y_u);
}
g.setColor(Color.black);
}
x1 *= 10.0;
y1 += sp;
}
//
// グラフの表示
//
g2.setStroke(new BasicStroke(line_w));
k1 = 0;
for (i1 = 0; i1 < n_g; i1++) {
g.setColor(cl[k1]);
kx1 = 0;
ky1 = 0;
for (i2 = 0; i2 < n_p; i2++) {
kx = x_l + (int)((x_r - x_l) * (data_xx[i1][i2] - xx_scale[0]) / (xx_scale[1] - xx_scale[0]));
ky = y_d - (int)((y_d - y_u) * (data_y[i1][i2] - y_scale[0]) / (y_scale[1] - y_scale[0]));
if (i2 > 0)
g.drawLine(kx1, ky1, kx, ky);
kx1 = kx;
ky1 = ky;
}
k1++;
if (k1 >= cl.length)
k1 = 0;
}
g2.setStroke(new BasicStroke(1.0f));
}
/**********************/
/* Windowのサイズ変化 */
/**********************/
class ComponentResize extends ComponentAdapter
{
public void componentResized(ComponentEvent e)
{
repaint();
}
}
/************/
/* 終了処理 */
/************/
class WinEnd extends WindowAdapter
{
public void windowClosing(WindowEvent e) {
setVisible(false);
}
}
/************************************/
/* マウスがクリックされたときの処理 */
/************************************/
class ClickMouse extends MouseAdapter
{
Bode dd;
ClickMouse(Bode dd1)
{
dd = dd1;
}
public void mouseClicked(MouseEvent e)
{
int xp = e.getX();
int yp = e.getY();
// グラフの色,線の太さ等
if (xp > bx1 && xp < bx2 && yp > by1 && yp < by2) {
Modify md = new Modify(dd);
md.setVisible(true);
}
}
}
}
/****************************/
/* 色及び線の太さの変更 */
/* coded by Y.Suganuma */
/****************************/
class Modify extends Dialog implements ActionListener, TextListener {
Bode dd; // ボード線図
Button bt_dd;
TextField rgb[];
TextField r[];
TextField g[];
TextField b[];
TextField tx;
Checkbox r1, r2;
float line_w = 1.0f; // 折れ線グラフ等の線の太さ
Color cl[]; // グラフの色
int n_g; // グラフの数
int wd; // 線の太さを変更するか
int n;
Panel jp[];
// ボード線図
Modify(Bode dd1)
{
super(dd1, "色と線の変更", true);
// 初期設定
Font f = new Font("TimesRoman", Font.BOLD, 20);
setFont(f);
dd = dd1;
wd = 1;
n_g = dd.n_g;
if (n_g > 10)
n_g = 10;
n = n_g + 2;
line_w = dd.line_w;
cl = new Color[n_g];
for (int i1 = 0; i1 < n_g; i1++)
cl[i1] = dd.cl[i1];
set();
// ボタン
bt_dd = new Button("OK");
bt_dd.addActionListener(this);
jp[n-1].add(bt_dd);
}
// 設定
void set()
{
setSize(450, 60*(n));
setBackground(Color.white);
setLayout(new GridLayout(n, 1, 5, 5));
jp = new Panel[n];
for (int i1 = 0; i1 < n; i1++) {
jp[i1] = new Panel();
add(jp[i1]);
}
// 色の変更
Label lb[][] = new Label[n_g][3];
rgb = new TextField[n_g];
r = new TextField[n_g];
g = new TextField[n_g];
b = new TextField[n_g];
for (int i1 = 0; i1 < n_g; i1++) {
rgb[i1] = new TextField(3);
rgb[i1].setBackground(new Color(cl[i1].getRed(), cl[i1].getGreen(), cl[i1].getBlue()));
jp[i1].add(rgb[i1]);
lb[i1][0] = new Label(" 赤");
jp[i1].add(lb[i1][0]);
r[i1] = new TextField(3);
r[i1].setBackground(Color.white);
r[i1].setText(Integer.toString(cl[i1].getRed()));
r[i1].addTextListener(this);
jp[i1].add(r[i1]);
lb[i1][1] = new Label("緑");
jp[i1].add(lb[i1][1]);
g[i1] = new TextField(3);
g[i1].setBackground(Color.white);
g[i1].setText(Integer.toString(cl[i1].getGreen()));
g[i1].addTextListener(this);
jp[i1].add(g[i1]);
lb[i1][2] = new Label("青");
jp[i1].add(lb[i1][2]);
b[i1] = new TextField(3);
b[i1].setBackground(Color.white);
b[i1].setText(Integer.toString(cl[i1].getBlue()));
b[i1].addTextListener(this);
jp[i1].add(b[i1]);
}
// 線の変更
if (wd > 0) {
Label lb1 = new Label("線の太さ:");
jp[n_g].add(lb1);
tx = new TextField(2);
tx.setBackground(Color.white);
tx.setText(Integer.toString((int)line_w));
jp[n_g].add(tx);
}
}
// TextFieldの内容が変更されたときの処理
public void textValueChanged(TextEvent e)
{
for (int i1 = 0; i1 < n_g; i1++) {
if (e.getSource() == r[i1] || e.getSource() == g[i1] || e.getSource() == b[i1]) {
String str = r[i1].getText();
int rc = str.length()>0 ? Integer.parseInt(str) : 0;
str = g[i1].getText();
int gc = str.length()>0 ? Integer.parseInt(str) : 0;
str = b[i1].getText();
int bc = str.length()>0 ? Integer.parseInt(str) : 0;
rgb[i1].setBackground(new Color(rc, gc, bc));
}
}
}
// 値の設定
public void actionPerformed(ActionEvent e)
{
for (int i1 = 0; i1 < n_g; i1++) {
String str = r[i1].getText();
int rc = str.length()>0 ? Integer.parseInt(str) : 0;
str = g[i1].getText();
int gc = str.length()>0 ? Integer.parseInt(str) : 0;
str = b[i1].getText();
int bc = str.length()>0 ? Integer.parseInt(str) : 0;
dd.cl[i1] = new Color(rc, gc, bc);
}
dd.line_w = Integer.parseInt(tx.getText());
dd.repaint();
setVisible(false);
}
}
/****************************/
/* クラスCoef */
/* coded by Y.Suganuma */
/****************************/
class Coef extends Panel implements TextListener
{
int type, no;
BodePlot ba;
TextField n_t;
TextField bun_t[];
Label lb[];
Panel pn;
/***************************/
/* コンストラクタ */
/* type_i : =0 : 分子 */
/* =1 : 分母 */
/* ba_i : BodePlot */
/* no_i : 式番号 */
/***************************/
Coef(int type_i, BodePlot ba_i, int no_i)
{
int i1;
type = type_i;
ba = ba_i;
no = no_i;
// 次数
setLayout(new BorderLayout(5, 10));
Panel pn1 = new Panel();
add(pn1, BorderLayout.NORTH);
if (type == 0)
pn1.add(new Label((no+1)+".分子の次数"));
else
pn1.add(new Label((no+1)+".分母の次数"));
n_t = new TextField(2);
n_t.addTextListener(this);
pn1.add(n_t);
// 係数
pn = new Panel();
add(pn, BorderLayout.CENTER);
}
/************************************/
/* パラメータが変更されたときの処理 */
/************************************/
public void textValueChanged(TextEvent e)
{
int i1, n;
ba.ta.setForeground(Color.black);
ba.ta.setText("");
try {
n = Integer.parseInt(n_t.getText());
if (n < 0) {
n_t.setText("0");
n = 0;
}
if (type == 0) {
ba.m[no] = n;
ba.si[no] = new double [n+1];
}
else {
ba.n[no] = n;
ba.bo[no] = new double [n+1];
}
remove(pn);
pn = new Panel();
add(pn, BorderLayout.CENTER);
pn.setLayout(new GridLayout(n+1, 1, 10, 0));
Panel pnx[] = new Panel [n+1];
bun_t = new TextField [n+1];
lb = new Label [n+1];
pnx[0] = new Panel();
pn.add(pnx[0]);
lb[0] = new Label("定数項");
pnx[0].add(lb[0]);
bun_t[0] = new TextField(3);
pnx[0].add(bun_t[0]);
for (i1 = 1; i1 <= n; i1++) {
pnx[i1] = new Panel();
pn.add(pnx[i1]);
lb[i1] = new Label("s の "+i1+" 次の項");
pnx[i1].add(lb[i1]);
bun_t[i1] = new TextField(3);
pnx[i1].add(bun_t[i1]);
}
getParent().validate();
}
catch (NumberFormatException em) {}
}
}
/****************************/
/* クラスComplex */
/* coded by Y.Suganuma */
/****************************/
class Complex {
private double r; // 実部
private double i; // 虚部
/******************/
/* コンストラクタ */
/* a : 実部 */
/* b : 虚部 */
/******************/
Complex(double a, double b)
{
r = a;
i = b;
}
/******************/
/* コンストラクタ */
/* a : 実部 */
/******************/
Complex(double a)
{
r = a;
i = 0.0;
}
/******************/
/* コンストラクタ */
/******************/
Complex()
{
r = 0.0;
i = 0.0;
}
/********/
/* 出力 */
/********/
void output(PrintStream out, Complex a)
{
out.print("(" + a.r + ", " + a.i + ")");
}
/******************/
/* 複素数の絶対値 */
/******************/
static double abs(Complex a)
{
double x;
x = Math.sqrt(a.r * a.r + a.i * a.i);
return x;
}
/****************/
/* 複素数の角度 */
/****************/
static double angle(Complex a)
{
double x;
if (a.r == 0.0 && a.i == 0.0)
x = 0.0;
else
x = Math.atan2(a.i, a.r);
return x;
}
/****************/
/* 複素数のn乗 */
/****************/
static Complex pow(Complex a, int n)
{
int i1;
Complex c = new Complex (1);
if (n >= 0) {
for (i1 = 0; i1 < n; i1++)
c = Complex.mul(c, a);
}
else {
for (i1 = 0; i1 < -n; i1++)
c = Complex.mul(c, a);
c = Complex.dev(new Complex(1.0), c);
}
return c;
}
/****************/
/* 複素数の加算 */
/****************/
static Complex add(Complex a, Complex b)
{
Complex c = new Complex();
c.r = a.r + b.r;
c.i = a.i + b.i;
return c;
}
/****************/
/* 複素数の減算 */
/****************/
static Complex sub(Complex a, Complex b)
{
Complex c = new Complex();
c.r = a.r - b.r;
c.i = a.i - b.i;
return c;
}
/****************/
/* 複素数の乗算 */
/****************/
static Complex mul(Complex a, Complex b)
{
Complex c = new Complex();
c.r = a.r * b.r - a.i * b.i;
c.i = a.i * b.r + a.r * b.i;
return c;
}
/****************/
/* 複素数の除算 */
/****************/
static Complex dev(Complex a, Complex b)
{
double x;
Complex c = new Complex();
x = 1.0 / (b.r * b.r + b.i * b.i);
c.r = (a.r * b.r + a.i * b.i) * x;
c.i = (a.i * b.r - a.r * b.i) * x;
return c;
}
}
/*****************************************/
/* 伝達関数のゲインと位相の計算(Swing) */
/* coded by Y.Suganuma */
/*****************************************/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;
import java.text.*;
public class Test {
public static void main (String[] args)
{
BodePlot_s bd = new BodePlot_s("ボード線図");
}
}
class BodePlot_s extends JFrame implements ActionListener, DocumentListener
{
double fl, fu, si[][], bo[][];
int k, m[], n[], n_g = -1;
JTextField fl_t, fu_t, k_t, n_g_t, ex[];
JTextArea ta;
JButton bt;
Coef bunsi[], bunbo[];
Container cp;
JScrollPane sp;
Font f = new Font("TimesRoman", Font.BOLD, 20);
/******************/
/* コンストラクタ */
/******************/
BodePlot_s(String name)
{
// Frameクラスのコンストラクタ(Windowのタイトルを引き渡す)
super(name);
// Windowの大きさ
setSize(790, 590);
// レイアウト,背景色,フォント
cp = getContentPane();
cp.setLayout(new BorderLayout(5, 5));
cp.setBackground(new Color(225, 255, 225));
// 上のパネル
JPanel pn1 = new JPanel();
pn1.setBackground(new Color(225, 255, 225));
pn1.setLayout(new GridLayout(2, 1, 5, 5));
cp.add(pn1, BorderLayout.NORTH);
JPanel pn11 = new JPanel();
pn11.setBackground(new Color(225, 255, 225));
pn1.add(pn11);
JLabel lb1 = new JLabel("式の数(グラフの数)");
lb1.setFont(f);
pn11.add(lb1);
n_g_t = new JTextField(3);
n_g_t.setFont(f);
n_g_t.getDocument().putProperty("name", "no");
n_g_t.getDocument().addDocumentListener(this);
pn11.add(n_g_t);
pn11.add(new JLabel(" "));
bt = new JButton("実行");
bt.setBackground(Color.pink);
bt.setFont(f);
bt.addActionListener(this);
pn11.add(bt);
JPanel pn12 = new JPanel();
pn12.setBackground(new Color(225, 255, 225));
pn1.add(pn12);
JLabel lb2 = new JLabel("周波数下限");
lb2.setFont(f);
pn12.add(lb2);
fl = 0.01;
fl_t = new JTextField("0.01", 3);
fl_t.setFont(f);
fl_t.getDocument().putProperty("name", "lower");
fl_t.getDocument().addDocumentListener(this);
pn12.add(fl_t);
JLabel lb3 = new JLabel(" 周波数上限");
lb3.setFont(f);
pn12.add(lb3);
fu = 100.0;
fu_t = new JTextField("100", 3);
fu_t.setFont(f);
fu_t.getDocument().putProperty("name", "upper");
fu_t.getDocument().addDocumentListener(this);
pn12.add(fu_t);
JLabel lb4 = new JLabel(" データ数");
lb4.setFont(f);
pn12.add(lb4);
k = 100;
k_t = new JTextField("100", 3);
k_t.setFont(f);
k_t.getDocument().putProperty("name", "data");
k_t.getDocument().addDocumentListener(this);
pn12.add(k_t);
// 中央のパネル
sp = new JScrollPane();
cp.add(sp, BorderLayout.CENTER);
// 下のパネル
JPanel pn6 = new JPanel();
pn6.setBackground(new Color(225, 255, 225));
cp.add(pn6, BorderLayout.SOUTH);
ta = new JTextArea(5, 35);
ta.setFont(f);
JScrollPane scroll2 = new JScrollPane(ta);
pn6.add(scroll2);
// ウィンドウを表示
setVisible(true);
// イベントアダプタ
addWindowListener(new WinEnd());
}
/************/
/* log10(x) */
/************/
static double log10(double x)
{
return Math.log(x) / Math.log(10.0);
}
/****************************************/
/* 伝達関数のsにjωを代入した値の計算 */
/* ff : ω(周波数) */
/* m : 分子の次数 */
/* si : 分子多項式の係数 */
/* n : 分母の次数 */
/* bo : 分母多項式の係数 */
/* return : 結果 */
/****************************************/
static Complex G_s(double ff, int m, double si[], int n, double bo[])
{
Complex f, x, y;
// 周波数を複素数に変換
f = new Complex (0.0, ff);
// 分子
x = value(f, m, si);
// 分母
y = value(f, n, bo);
return Complex.dev(x, y);
}
/**************************************/
/* 多項式のsにjωを代入した値の計算 */
/* f : jω(周波数,複素数) */
/* n : 多項式の次数 */
/* a : 多項式の係数 */
/* return : 結果 */
/**************************************/
static Complex value(Complex f, int n, double a[])
{
int i1, k1;
Complex x;
x = new Complex (0.0, 0.0);
for (i1 = 0; i1 <= n; i1++)
x = Complex.add(x, Complex.mul(new Complex(a[i1]), Complex.pow(f, i1)));
return x;
}
/******************************/
/* 上,左,下,右の余白の設定 */
/******************************/
public Insets getInsets()
{
return new Insets(70, 20, 20, 20);
}
/******************************/
/* ボタンが押されたときの処理 */
/******************************/
public void actionPerformed(ActionEvent e)
{
double x, h, f, ff, g_min, g_max, p_min, p_max, uc = 90.0 / Math.asin(1.0);
int i1, i2, k1, p, sw = 0;
String g_title[] = null;
Complex g;
ta.setForeground(Color.black);
ta.setText("");
// エラーの判定
if (n_g < 0) {
sw = 1;
ta.setForeground(Color.red);
ta.append(" 式の数を入力してください\n");
}
else {
g_title = new String [n_g];
for (i1 = 0; i1 < n_g; i1++) {
if (ex[i1].getText().length() <= 0) {
sw = 1;
ta.setForeground(Color.red);
ta.append(" " + (i1+1) + " 番目の式の説明(凡例)を入力してください\n");
}
else
g_title[i1] = ex[i1].getText();
}
for (i1 = 0; i1 < n_g; i1++) {
if (m[i1] < 0) {
sw = 1;
ta.setForeground(Color.red);
ta.append(" " + (i1+1) + " 番目の式の分子の次数を入力してください\n");
}
else {
for (i2 = 0; i2 <= m[i1]; i2++) {
if (bunsi[i1].bun_t[i2].getText().length() <= 0) {
sw = 1;
ta.setForeground(Color.red);
ta.append(" " + (i1+1) + " 番目の式の分子の s の " + i2 + " 次の係数を入力してください\n");
}
else
si[i1][i2] = Double.parseDouble(bunsi[i1].bun_t[i2].getText());
}
}
}
for (i1 = 0; i1 < n_g; i1++) {
if (n[i1] < 0) {
sw = 1;
ta.setForeground(Color.red);
ta.append(" " + (i1+1) + " 番目の式の分母の次数を入力してください\n");
}
else {
for (i2 = 0; i2 <= n[i1]; i2++) {
if (bunbo[i1].bun_t[i2].getText().length() <= 0) {
sw = 1;
ta.setForeground(Color.red);
ta.append(" " + (i1+1) + " 番目の式の分母の s の " + i2 + " 次の係数を入力してください\n");
}
else
bo[i1][i2] = Double.parseDouble(bunbo[i1].bun_t[i2].getText());
}
}
}
}
// ゲインと位相の計算
if (sw == 0) {
// 下限と上限の再設定
if (fl < 1.0) {
x = 0.1;
while (fl < x-1.0e-10)
x /= 10.0;
fl = x;
}
else {
x = 1.0;
while (fl > x-1.0e-10)
x *= 10.0;
fl = x;
}
if (fu < 1.0) {
x = 0.1;
while (fu < x+1.0e-10)
x /= 10.0;
fu = 10.0 * x;
}
else {
x = 1.0;
while (fu > x+1.0e-10)
x *= 10.0;
fu = x;
}
// 初期設定
double freq1[][] = new double [n_g][k+1];
double freq2[][] = new double [n_g][k+1];
double gain[][] = new double [n_g][k+1];
double phase[][] = new double [n_g][k+1];
h = (log10(fu) - log10(fl)) / k;
g_min = 0.0;
g_max = 0.0;
p_min = 0.0;
p_max = 0.0;
ta.setText(" 角周波数 ゲイン(dB) 位相(度)\n");
for (i1 = 0; i1 < n_g; i1++) {
ff = log10(fl);
ta.append(g_title[i1] + "\n");
for (i2 = 0; i2 <= k; i2++) {
// 周波数の対数を元に戻す
f = Math.pow(10.0, ff);
freq1[i1][i2] = f;
freq2[i1][i2] = f;
ta.append(" " + f);
// 値の計算
g = G_s(f, m[i1], si[i1], n[i1], bo[i1]);
// ゲインと位相の計算
gain[i1][i2] = 20.0 * log10(Complex.abs(g));
ta.append(" " + gain[i1][i2]);
if (i1 == 0 && i2 == 0) {
g_min = gain[i1][i2];
g_max = gain[i1][i2];
}
else {
if (gain[i1][i2] > g_max)
g_max = gain[i1][i2];
else if (gain[i1][i2] < g_min)
g_min = gain[i1][i2];
}
x = Complex.angle(g) * uc;
if (i2 > 0) {
while (Math.abs(phase[i1][i2-1]-x) > 180.0) {
if (x-phase[i1][i2-1] > 180.0)
x -= 360.0;
else {
if (x-phase[i1][i2-1] < -180.0)
x += 360.0;
}
}
}
phase[i1][i2] = x;
ta.append(" " + x + "\n");
if (i1 == 0 && i2 == 0) {
p_min = phase[i1][i2];
p_max = phase[i1][i2];
}
else {
if (phase[i1][i2] > p_max)
p_max = phase[i1][i2];
else if (phase[i1][i2] < p_min)
p_min = phase[i1][i2];
}
// 次の周波数
ff += h;
}
}
// グラフの描画
// グラフ,x軸,及び,y軸のタイトル
String title1[] = new String [3];
title1[0] = "ゲイン線図";
title1[1] = "角周波数";
title1[2] = "ゲイン(dB)";
// ゲイン線図
// x軸目盛り
double x_scale1[] = new double[3];
x_scale1[0] = fl; // 最小値
x_scale1[1] = fu; // 最大値
x_scale1[2] = 1.0; // 最大値
// y軸目盛り
double y_scale1[] = new double[3];
if ((g_max-g_min) < 1.0e-5) {
if (g_min > 0.0) {
k1 = (int)Math.round(g_min / 20);
y_scale1[0] = 20.0 * k1 - 20.0; // 最小値
y_scale1[1] = 20.0 * k1 + 20.0; // 最大値
}
else {
k1 = (int)Math.round(-g_min / 20);
y_scale1[0] = -20.0 * k1 - 20.0; // 最小値
y_scale1[1] = -20.0 * k1 + 20.0; // 最大値
}
}
else {
if (g_min > 0.0) {
k1 = (int)(g_min / 20);
y_scale1[0] = 20.0 * k1; // 最小値
}
else {
k1 = (int)(-g_min / 20);
if (Math.abs(-20.0*k1-g_min) > 1.0e-5)
k1++;
y_scale1[0] = -20.0 * k1; // 最小値
}
if (g_max > 0.0) {
k1 = (int)(g_max / 20);
if (Math.abs(20.0*k1-g_max) > 1.0e-5)
k1++;
y_scale1[1] = 20.0 * k1; // 最大値
}
else {
k1 = (int)(-g_max / 20);
y_scale1[1] = -20.0 * k1; // 最大値
}
}
y_scale1[2] = 20.0; // 刻み幅
// x軸の小数点以下桁数
p = 0;
if (fl < 1.0) {
p = 1;
x = 0.1;
while (fl < x-1.0e-10) {
x /= 10.0;
p++;
}
}
Bode gp1 = new Bode(title1, g_title, x_scale1, p, y_scale1, 0, freq1, gain, true, true);
// 位相線図
// グラフ,x軸,及び,y軸のタイトル
String title2[] = new String [3];
title2[0] = "位相線図";
title2[1] = "角周波数";
title2[2] = "位相(度)";
// x軸目盛り
double x_scale2[] = new double[3];
x_scale2[0] = fl; // 最小値
x_scale2[1] = fu; // 最大値
x_scale2[2] = 1.0; // 最大値
// y軸目盛り
double y_scale2[] = new double[3];
if ((p_max-p_min) < 1.0e-5) {
if (p_min > 0.0) {
k1 = (int)Math.round(p_min / 90);
y_scale2[0] = 90.0 * k1 - 90.0; // 最小値
y_scale2[1] = 90.0 * k1 + 90.0; // 最大値
}
else {
k1 = (int)Math.round(-p_min / 90);
y_scale2[0] = -90.0 * k1 - 90.0; // 最小値
y_scale2[1] = -90.0 * k1 + 90.0; // 最大値
}
}
else {
if (p_min > 0.0) {
k1 = (int)(p_min / 90);
y_scale2[0] = 90.0 * k1; // 最小値
}
else {
k1 = (int)(-p_min / 90);
if (Math.abs(-90.0*k1-p_min) > 1.0e-5)
k1++;
y_scale2[0] = -90.0 * k1; // 最小値
}
if (p_max > 0.0) {
k1 = (int)(p_max / 90);
if (Math.abs(90.0*k1-p_max) > 1.0e-5)
k1++;
y_scale2[1] = 90.0 * k1; // 最大値
}
else {
k1 = (int)(-p_max / 90);
y_scale2[1] = -90.0 * k1; // 最大値
}
}
y_scale2[2] = 90.0; // 刻み幅
Bode gp2 = new Bode(title2, g_title, x_scale2, p, y_scale2, 0, freq2, phase, true, true);
}
}
/************************************/
/* パラメータが変更されたときの処理 */
/************************************/
public void changedUpdate(DocumentEvent e) {}
public void removeUpdate(DocumentEvent e) {}
public void insertUpdate(DocumentEvent e)
{
int i1;
String key = e.getDocument().getProperty("name").toString();
try {
if (key.equals("no")) {
n_g = Integer.parseInt(n_g_t.getText());
ta.setForeground(Color.black);
ta.setText("");
if (n_g <= 0) {
ta.setForeground(Color.red);
ta.setText(" 0 より大きい数値を入力してください");
}
else {
remove(sp);
si = new double [n_g][];
bo = new double [n_g][];
m = new int [n_g];
n = new int [n_g];
for (i1 = 0; i1 < n_g; i1++) {
m[i1] = -1;
n[i1] = -1;
}
JPanel pn2 = new JPanel();
pn2.setBackground(new Color(225, 255, 225));
pn2.setLayout(new GridLayout(n_g, 1, 5, 5));
sp = new JScrollPane(pn2);
JScrollPane sp1[] = new JScrollPane [n_g];
JScrollPane sp2[] = new JScrollPane [n_g];
JPanel pn3[] = new JPanel [n_g];
JPanel pn4[] = new JPanel [n_g];
JPanel pn5[] = new JPanel [n_g];
JLabel lb[] = new JLabel [n_g];
ex = new JTextField [n_g];
bunsi = new Coef [n_g];
bunbo = new Coef [n_g];
for (i1 = 0; i1 < n_g; i1++) {
pn3[i1] = new JPanel();
pn3[i1].setBackground(new Color(255, 255, 225));
pn3[i1].setLayout(new BorderLayout(5, 5));
pn2.add(pn3[i1]);
pn4[i1] = new JPanel();
pn4[i1].setBackground(Color.white);
lb[i1] = new JLabel((i1+1) + "番目の式の説明:");
lb[i1].setFont(f);
pn4[i1].add(lb[i1]);
ex[i1] = new JTextField(10);
ex[i1].setFont(f);
pn4[i1].add(ex[i1]);
pn3[i1].add(pn4[i1], BorderLayout.NORTH);
pn5[i1] = new JPanel();
pn5[i1].setBackground(Color.white);
pn5[i1].setLayout(new GridLayout(1, 2, 5, 5));
bunsi[i1] = new Coef(0, this, i1);
sp1[i1] = new JScrollPane(bunsi[i1]);
pn5[i1].add(sp1[i1]);
bunbo[i1] = new Coef(1, this, i1);
sp2[i1] = new JScrollPane(bunbo[i1]);
pn5[i1].add(sp2[i1]);
pn3[i1].add(pn5[i1], BorderLayout.CENTER);
}
cp.add(sp, BorderLayout.CENTER);
validate();
}
}
else if (key.equals("lower")) {
fl = Double.parseDouble(fl_t.getText());
fu = Double.parseDouble(fu_t.getText());
ta.setForeground(Color.black);
ta.setText("");
if (fl <= 0.0) {
ta.setForeground(Color.red);
ta.setText(" 0 より大きい数値を入力してください");
}
else if (fu <= fl) {
ta.setForeground(Color.red);
ta.setText(" 上限より小さい数値を入力してください");
}
}
else if (key.equals("upper")) {
fl = Double.parseDouble(fl_t.getText());
fu = Double.parseDouble(fu_t.getText());
ta.setForeground(Color.black);
ta.setText("");
if (fu <= 0.0) {
ta.setForeground(Color.red);
ta.setText(" 0 より大きい数値を入力してください");
}
else if (fu <= fl) {
ta.setForeground(Color.red);
ta.setText(" 下限より大きい数値を入力してください");
}
}
else if (key.equals("data")) {
k = Integer.parseInt(k_t.getText());
ta.setForeground(Color.black);
ta.setText("");
if (k <= 0) {
ta.setForeground(Color.red);
ta.setText(" 0 より大きい数値を入力してください");
}
}
}
catch (NumberFormatException em) {}
}
/************/
/* 終了処理 */
/************/
class WinEnd extends WindowAdapter
{
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
}
/****************************/
/* ボード線図の描画 */
/* coded by Y.Suganuma */
/****************************/
class Bode extends JFrame {
Draw_bode pn;
/*********************************************************/
/* コンストラクタ */
/* title_i : グラフ,x軸,及び,y軸のタイトル */
/* g_title_i : 凡例 */
/* x_scale_i : データの最小値,最大値,目盛幅(y) */
/* place_x_i : 小数点以下の桁数(x軸) */
/* y_scale_i : データの最小値,最大値,目盛幅(y) */
/* place_y_i : 小数点以下の桁数(y軸) */
/* data_x_i : グラフのデータ(x軸) */
/* data_y_i : グラフのデータ(y軸) */
/* d_t_i : タイトル表示の有無 */
/* d_g_i : 凡例表示の有無 */
/*********************************************************/
Bode(String title_i[], String g_title_i[], double x_scale_i[],
int place_x_i, double y_scale_i[], int place_y_i,
double data_x_i[][], double data_y_i[][], boolean d_t_i,
boolean d_g_i)
{
// JFrameクラスのコンストラクタの呼び出し
super("ボード線図");
// Windowサイズと表示位置を設定
int width = 900, height = 600; // Windowの大きさ(初期サイズ)
setSize(width, height);
Toolkit tool = getToolkit();
Dimension d = tool.getScreenSize();
setLocation(d.width / 2 - width / 2, d.height / 2 - height / 2);
// 描画パネル
Container cp = getContentPane();
pn = new Draw_bode(title_i, g_title_i, x_scale_i, place_x_i, y_scale_i, place_y_i, data_x_i, data_y_i, d_t_i, d_g_i, this);
cp.add(pn);
// ウィンドウを表示
setVisible(true);
// イベントアダプタ
addWindowListener(new WinEnd());
addComponentListener(new ComponentResize());
}
/**********************/
/* Windowのサイズ変化 */
/**********************/
class ComponentResize extends ComponentAdapter
{
public void componentResized(ComponentEvent e)
{
pn.repaint();
}
}
/************/
/* 終了処理 */
/************/
class WinEnd extends WindowAdapter
{
public void windowClosing(WindowEvent e) {
setVisible(false);
}
}
}
class Draw_bode extends JPanel {
String title[]; // グラフのタイトル
String g_title[]; // 凡例(グラフの内容)
double xx_scale[]; // y軸目盛り
double x_scale[]; // 元のy軸目盛り
double y_scale[]; // y軸目盛り
double data_x[][]; // 元のデータ
double data_xx[][], data_y[][]; // データ
boolean d_t; // タイトル表示の有無
boolean d_g; // 凡例表示の有無
boolean log_c = false; // 対数に変換したか否か
int place_x; // 小数点以下の桁数(x軸)
int place_y; // 小数点以下の桁数(y軸)
int width = 900, height = 600; // Windowの大きさ(初期サイズ)
int bx1, bx2, by1, by2; // 表示切り替えボタンの位置
Bode bd;
String change = " 色 "; // 表示切り替えボタン
float line_w = 1.0f; // 折れ線グラフ等の線の太さ
Color cl[] = {Color.black, Color.magenta, Color.blue, Color.orange, Color.cyan,
Color.pink, Color.green, Color.yellow, Color.darkGray, Color.red}; // グラフの色
int n_g; // グラフの数
/******************/
/* コンストラクタ */
/******************/
Draw_bode(String title_i[], String g_title_i[], double x_scale_i[],
int place_x_i, double y_scale_i[], int place_y_i,
double data_x_i[][], double data_y_i[][], boolean d_t_i,
boolean d_g_i, Bode bd1) {
// 背景色
setBackground(Color.white);
// テーブルデータの保存
title = title_i;
g_title = g_title_i;
x_scale = x_scale_i;
place_x = place_x_i;
y_scale = y_scale_i;
place_y = place_y_i;
data_x = data_x_i;
data_y = data_y_i;
d_t = d_t_i;
d_g = d_g_i;
bd = bd1;
int i1, i2;
int n_g = g_title.length;
int n_p = data_x[0].length;
xx_scale = new double [3];
data_xx = new double [n_g][n_p];
xx_scale[0] = x_scale[0];
xx_scale[1] = x_scale[1];
for (i1 = 0; i1 < n_g; i1++) {
for (i2 = 0; i2 < n_p; i2++)
data_xx[i1][i2] = data_x[i1][i2];
}
// イベントアダプタ
addMouseListener(new ClickMouse(this));
}
/********/
/* 描画 */
/********/
public void paintComponent (Graphics g)
{
super.paintComponent(g); // 親クラスの描画(必ず必要)
double r, x1, y1, y2, sp, x_scale_org = 0.0;
int i1, i2, k, k_x, k_y, k1, k2, kx, kx1, ky, ky1, han, len;
int x_l, x_r, y_u, y_d; // 描画領域
int f_size; // フォントサイズ
int n_p; // データの数
String s1;
Font f;
FontMetrics fm;
Graphics2D g2 = (Graphics2D)g;
//
// Windowサイズの取得
//
Insets insets = bd.getInsets();
Dimension d = bd.getSize();
width = d.width - (insets.left + insets.right);
height = d.height - (insets.top + insets.bottom);
x_l = insets.left + 10;
x_r = d.width - insets.right - 10;
y_u = 20;
y_d = d.height - insets.bottom - insets.top;
//
// グラフタイトルの表示
//
r = 0.05; // タイトル領域の割合
f_size = ((y_d - y_u) < (x_r - x_l)) ? (int)((y_d - y_u) * r) : (int)((x_r - x_l) * r);
if (f_size < 5)
f_size = 5;
if (d_t) {
f = new Font("TimesRoman", Font.BOLD, f_size);
g.setFont(f);
fm = g.getFontMetrics(f);
len = fm.stringWidth(title[0]);
g.drawString(title[0], (x_l+x_r)/2-len/2, y_d-f_size/2);
y_d -= f_size;
}
//
// 表示切り替えボタンの設置
//
f_size = (int)(0.8 * f_size);
if (f_size < 5)
f_size = 5;
f = new Font("TimesRoman", Font.PLAIN, f_size);
fm = g.getFontMetrics(f);
g.setFont(f);
g.setColor(Color.yellow);
len = fm.stringWidth(change);
bx1 = x_r - len - 7 * f_size / 10;
by1 = y_u - f_size / 2;
bx2 = bx1 + len + f_size / 2;
by2 = by1 + 6 * f_size / 5;
g.fill3DRect(bx1, by1, len+f_size/2, 6*f_size/5, true);
g.setColor(Color.black);
g.drawString(change, x_r-len-f_size/2, y_u+f_size/2);
//
// 凡例の表示
//
n_g = g_title.length;
if (d_g) {
han = 0;
for (i1 = 0; i1 < n_g; i1++) {
len = fm.stringWidth(g_title[i1]);
if (len > han)
han = len;
}
han += 15;
r = 0.2; // 凡例領域の割合
k1 = (int)((x_r - x_l) * r);
if (han > k1)
han = k1;
kx = x_r - han;
ky = y_u + 3 * f_size / 2;
k = 0;
g2.setStroke(new BasicStroke(7.0f));
for (i1 = 0; i1 < n_g; i1++) {
g.setColor(cl[k]);
g.drawLine(kx, ky, kx+10, ky);
g.setColor(Color.black);
g.drawString(g_title[i1], kx+15, ky+2*f_size/5);
k++;
if (k >= cl.length)
k = 0;
ky += f_size;
}
g2.setStroke(new BasicStroke(1.0f));
x_r -= (han + 10);
}
else
x_r -= (int)(0.03 * (x_r - x_l));
//
// x軸の対数
//
n_p = data_x[0].length;
x_scale_org = x_scale[0];
xx_scale[0] = Math.log(x_scale[0]) / Math.log(10.0);
xx_scale[1] = Math.log(x_scale[1]) / Math.log(10.0);
xx_scale[2] = 1.0;
for (i1 = 0; i1 < n_g; i1++) {
for (i2 = 0; i2 < n_p; i2++)
data_xx[i1][i2] = Math.log(data_x[i1][i2]) / Math.log(10.0);
}
//
// x軸及びy軸のタイトルの表示
//
if (title[1].length() > 0 && !title[1].equals("-")) {
len = fm.stringWidth(title[1]);
g.drawString(title[1], (x_l+x_r)/2-len/2, y_d-4*f_size/5);
y_d -= 7 * f_size / 4;
}
else
y_d -= f_size / 2;
if (title[2].length() > 0 && !title[2].equals("-")) {
g.drawString(title[2], x_l, y_u+f_size/2);
y_u += f_size;
}
//
// x軸,y軸,及び,各軸の目盛り
//
f_size = (int)(0.8 * f_size);
if (f_size < 5)
f_size = 5;
f = new Font("TimesRoman", Font.PLAIN, f_size);
fm = g.getFontMetrics(f);
y_d -= 3 * f_size / 2;
k_y = (int)((y_scale[1] - y_scale[0]) / (0.99 * y_scale[2]));
k_x = (int)((xx_scale[1] - xx_scale[0]) / (0.99 * xx_scale[2]));
g.setFont(f);
DecimalFormat df_x, df_y;
df_x = new DecimalFormat("#");
df_y = new DecimalFormat("#");
if (place_x != 0) {
s1 = "0.";
for (i1 = 0; i1 < place_x; i1++)
s1 += "0";
df_x = new DecimalFormat(s1);
}
if (place_y != 0) {
s1 = "#.";
for (i1 = 0; i1 < place_y; i1++)
s1 += "0";
df_y = new DecimalFormat(s1);
}
// y軸
y1 = y_scale[0];
len = 0;
for (i1 = 0; i1 < k_y+1; i1++) {
s1 = df_y.format(y1);
k1 = fm.stringWidth(s1);
if (k1 > len)
len = k1;
y1 += y_scale[2];
}
g.drawLine(x_l+len+5, y_u, x_l+len+5, y_d);
g.drawLine(x_r, y_u, x_r, y_d);
y1 = y_scale[0];
x1 = y_d;
sp = (double)(y_d - y_u) / k_y;
for (i1 = 0; i1 < k_y+1; i1++) {
ky = (int)Math.round(x1);
s1 = df_y.format(y1);
k1 = fm.stringWidth(s1);
g.drawString(s1, x_l+len-k1, ky+f_size/2);
g.drawLine(x_l+len+5, ky, x_r, ky);
y1 += y_scale[2];
x1 -= sp;
}
x_l += (len + 5);
// x軸
x1 = x_scale_org;
y1 = x_l;
sp = (double)(x_r - x_l) / k_x;
for (i1 = 0; i1 < k_x+1; i1++) {
kx = (int)Math.round(y1);
s1 = df_x.format(x1);
k1 = fm.stringWidth(s1);
g.drawString(s1, kx-k1/2, y_d+6*f_size/5);
g.drawLine(kx, y_d, kx, y_u);
if (i1 != k_x) {
g.setColor(Color.darkGray);
for (i2 = 2; i2 <= 9; i2++) {
y2 = Math.log(x1 * i2) / Math.log(10.0);
kx = x_l + (int)Math.round(((x_r - x_l) * (y2 - xx_scale[0]) / (xx_scale[1] - xx_scale[0])));
g.drawLine(kx, y_d, kx, y_u);
}
g.setColor(Color.black);
}
x1 *= 10.0;
y1 += sp;
}
//
// グラフの表示
//
g2.setStroke(new BasicStroke(line_w));
k1 = 0;
for (i1 = 0; i1 < n_g; i1++) {
g.setColor(cl[k1]);
kx1 = 0;
ky1 = 0;
for (i2 = 0; i2 < n_p; i2++) {
kx = x_l + (int)((x_r - x_l) * (data_xx[i1][i2] - xx_scale[0]) / (xx_scale[1] - xx_scale[0]));
ky = y_d - (int)((y_d - y_u) * (data_y[i1][i2] - y_scale[0]) / (y_scale[1] - y_scale[0]));
if (i2 > 0)
g.drawLine(kx1, ky1, kx, ky);
kx1 = kx;
ky1 = ky;
}
k1++;
if (k1 >= cl.length)
k1 = 0;
}
g2.setStroke(new BasicStroke(1.0f));
}
/************************************/
/* マウスがクリックされたときの処理 */
/************************************/
class ClickMouse extends MouseAdapter
{
Draw_bode dd;
ClickMouse(Draw_bode dd1)
{
dd = dd1;
}
public void mouseClicked(MouseEvent e)
{
int xp = e.getX();
int yp = e.getY();
// グラフの色,線の太さ等
if (xp > bx1 && xp < bx2 && yp > by1 && yp < by2) {
Modify md = new Modify(dd.bd, dd);
md.setVisible(true);
}
}
}
}
/****************************/
/* 色及び線の太さの変更 */
/* coded by Y.Suganuma */
/****************************/
class Modify extends JDialog implements ActionListener, TextListener {
Draw_bode dd; // ボード線図
JButton bt_dd;
TextField rgb[];
TextField r[];
TextField g[];
TextField b[];
JTextField tx;
JRadioButton r1, r2;
float line_w = 1.0f; // 折れ線グラフ等の線の太さ
Color cl[]; // グラフの色
int n_g; // グラフの数
int wd; // 線の太さを変更するか
int n;
JPanel jp[];
// ボード線図
Modify(Frame host, Draw_bode dd1)
{
super(host, "色と線の変更", true);
// 初期設定
dd = dd1;
wd = 1;
n_g = dd.n_g;
if (n_g > 10)
n_g = 10;
n = n_g + 2;
line_w = dd.line_w;
cl = new Color[n_g];
for (int i1 = 0; i1 < n_g; i1++)
cl[i1] = dd.cl[i1];
set();
// ボタン
Font f = new Font("TimesRoman", Font.BOLD, 20);
bt_dd = new JButton("OK");
bt_dd.setFont(f);
bt_dd.addActionListener(this);
jp[n-1].add(bt_dd);
}
// 設定
void set()
{
setSize(450, 60*(n));
Container cp = getContentPane();
cp.setBackground(Color.white);
cp.setLayout(new GridLayout(n, 1, 5, 5));
jp = new JPanel[n];
for (int i1 = 0; i1 < n; i1++) {
jp[i1] = new JPanel();
cp.add(jp[i1]);
}
Font f = new Font("TimesRoman", Font.BOLD, 20);
// 色の変更
JLabel lb[][] = new JLabel[n_g][3];
rgb = new TextField[n_g];
r = new TextField[n_g];
g = new TextField[n_g];
b = new TextField[n_g];
for (int i1 = 0; i1 < n_g; i1++) {
rgb[i1] = new TextField(3);
rgb[i1].setFont(f);
rgb[i1].setBackground(new Color(cl[i1].getRed(), cl[i1].getGreen(), cl[i1].getBlue()));
jp[i1].add(rgb[i1]);
lb[i1][0] = new JLabel(" 赤");
lb[i1][0].setFont(f);
jp[i1].add(lb[i1][0]);
r[i1] = new TextField(3);
r[i1].setFont(f);
r[i1].setBackground(Color.white);
r[i1].setText(Integer.toString(cl[i1].getRed()));
r[i1].addTextListener(this);
jp[i1].add(r[i1]);
lb[i1][1] = new JLabel("緑");
lb[i1][1].setFont(f);
jp[i1].add(lb[i1][1]);
g[i1] = new TextField(3);
g[i1].setFont(f);
g[i1].setBackground(Color.white);
g[i1].setText(Integer.toString(cl[i1].getGreen()));
g[i1].addTextListener(this);
jp[i1].add(g[i1]);
lb[i1][2] = new JLabel("青");
lb[i1][2].setFont(f);
jp[i1].add(lb[i1][2]);
b[i1] = new TextField(3);
b[i1].setFont(f);
b[i1].setBackground(Color.white);
b[i1].setText(Integer.toString(cl[i1].getBlue()));
b[i1].addTextListener(this);
jp[i1].add(b[i1]);
}
// 線の変更
if (wd > 0) {
JLabel lb1 = new JLabel("線の太さ:");
lb1.setFont(f);
jp[n_g].add(lb1);
tx = new JTextField(2);
tx.setFont(f);
tx.setBackground(Color.white);
tx.setText(Integer.toString((int)line_w));
jp[n_g].add(tx);
}
}
// TextFieldの内容が変更されたときの処理
public void textValueChanged(TextEvent e)
{
for (int i1 = 0; i1 < n_g; i1++) {
if (e.getSource() == r[i1] || e.getSource() == g[i1] || e.getSource() == b[i1]) {
String str = r[i1].getText();
int rc = str.length()>0 ? Integer.parseInt(str) : 0;
str = g[i1].getText();
int gc = str.length()>0 ? Integer.parseInt(str) : 0;
str = b[i1].getText();
int bc = str.length()>0 ? Integer.parseInt(str) : 0;
rgb[i1].setBackground(new Color(rc, gc, bc));
}
}
}
// 値の設定
public void actionPerformed(ActionEvent e)
{
for (int i1 = 0; i1 < n_g; i1++) {
String str = r[i1].getText();
int rc = str.length()>0 ? Integer.parseInt(str) : 0;
str = g[i1].getText();
int gc = str.length()>0 ? Integer.parseInt(str) : 0;
str = b[i1].getText();
int bc = str.length()>0 ? Integer.parseInt(str) : 0;
dd.cl[i1] = new Color(rc, gc, bc);
}
dd.line_w = Integer.parseInt(tx.getText());
dd.repaint();
setVisible(false);
}
}
/****************************/
/* クラスCoef */
/* coded by Y.Suganuma */
/****************************/
class Coef extends JPanel implements DocumentListener
{
int type, no;
BodePlot_s ba;
JTextField n_t;
JTextField bun_t[];
JLabel lb[];
JPanel pn;
Font f = new Font("TimesRoman", Font.BOLD, 20);
/****************************/
/* コンストラクタ */
/* type_i : =0 : 分子 */
/* =1 : 分母 */
/* ba_i : BodePlot_s */
/* no_i : 式番号 */
/****************************/
Coef(int type_i, BodePlot_s ba_i, int no_i)
{
int i1;
type = type_i;
ba = ba_i;
no = no_i;
setBackground(Color.white);
// 次数
setLayout(new BorderLayout(5, 5));
JPanel pn1 = new JPanel();
pn1.setBackground(Color.white);
add(pn1, BorderLayout.NORTH);
String str;
if (type == 0)
str = (no + 1) + ".分子の次数";
else
str = (no + 1) + ".分母の次数";
JLabel jisu = new JLabel(str);
jisu.setFont(f);
pn1.add(jisu);
n_t = new JTextField(2);
n_t.setFont(f);
n_t.getDocument().addDocumentListener(this);
pn1.add(n_t);
// 係数
pn = new JPanel();
add(pn, BorderLayout.CENTER);
}
/************************************/
/* パラメータが変更されたときの処理 */
/************************************/
public void changedUpdate(DocumentEvent e) {}
public void removeUpdate(DocumentEvent e) {}
public void insertUpdate(DocumentEvent e)
{
int i1, n;
ba.ta.setForeground(Color.black);
ba.ta.setText("");
try {
n = Integer.parseInt(n_t.getText());
if (n < 0) {
n_t.setText("0");
n = 0;
}
if (type == 0) {
ba.m[no] = n;
ba.si[no] = new double [n+1];
}
else {
ba.n[no] = n;
ba.bo[no] = new double [n+1];
}
remove(pn);
pn = new JPanel();
pn.setBackground(Color.white);
pn.setLayout(new GridLayout(n+1, 1, 5, 0));
add(pn, BorderLayout.CENTER);
JPanel pnx[] = new JPanel [n+1];
bun_t = new JTextField [n+1];
lb = new JLabel [n+1];
pnx[0] = new JPanel();
pnx[0].setBackground(Color.white);
pn.add(pnx[0]);
lb[0] = new JLabel("定数項");
lb[0].setFont(f);
pnx[0].add(lb[0]);
bun_t[0] = new JTextField(3);
bun_t[0].setFont(f);
pnx[0].add(bun_t[0]);
for (i1 = 1; i1 <= n; i1++) {
pnx[i1] = new JPanel();
pnx[i1].setBackground(Color.white);
pn.add(pnx[i1]);
lb[i1] = new JLabel("s の "+i1+" 次の項");
lb[i1].setFont(f);
pnx[i1].add(lb[i1]);
bun_t[i1] = new JTextField(3);
bun_t[i1].setFont(f);
pnx[i1].add(bun_t[i1]);
}
getParent().validate();
}
catch (NumberFormatException em) {}
}
}
/****************************/
/* クラスComplex */
/* coded by Y.Suganuma */
/****************************/
class Complex {
private double r; // 実部
private double i; // 虚部
/******************/
/* コンストラクタ */
/* a : 実部 */
/* b : 虚部 */
/******************/
Complex(double a, double b)
{
r = a;
i = b;
}
/******************/
/* コンストラクタ */
/* a : 実部 */
/******************/
Complex(double a)
{
r = a;
i = 0.0;
}
/******************/
/* コンストラクタ */
/******************/
Complex()
{
r = 0.0;
i = 0.0;
}
/********/
/* 出力 */
/********/
void output(PrintStream out, Complex a)
{
out.print("(" + a.r + ", " + a.i + ")");
}
/******************/
/* 複素数の絶対値 */
/******************/
static double abs(Complex a)
{
double x;
x = Math.sqrt(a.r * a.r + a.i * a.i);
return x;
}
/****************/
/* 複素数の角度 */
/****************/
static double angle(Complex a)
{
double x;
if (a.r == 0.0 && a.i == 0.0)
x = 0.0;
else
x = Math.atan2(a.i, a.r);
return x;
}
/****************/
/* 複素数のn乗 */
/****************/
static Complex pow(Complex a, int n)
{
int i1;
Complex c = new Complex (1);
if (n >= 0) {
for (i1 = 0; i1 < n; i1++)
c = Complex.mul(c, a);
}
else {
for (i1 = 0; i1 < -n; i1++)
c = Complex.mul(c, a);
c = Complex.dev(new Complex(1.0), c);
}
return c;
}
/****************/
/* 複素数の加算 */
/****************/
static Complex add(Complex a, Complex b)
{
Complex c = new Complex();
c.r = a.r + b.r;
c.i = a.i + b.i;
return c;
}
/****************/
/* 複素数の減算 */
/****************/
static Complex sub(Complex a, Complex b)
{
Complex c = new Complex();
c.r = a.r - b.r;
c.i = a.i - b.i;
return c;
}
/****************/
/* 複素数の乗算 */
/****************/
static Complex mul(Complex a, Complex b)
{
Complex c = new Complex();
c.r = a.r * b.r - a.i * b.i;
c.i = a.i * b.r + a.r * b.i;
return c;
}
/****************/
/* 複素数の除算 */
/****************/
static Complex dev(Complex a, Complex b)
{
double x;
Complex c = new Complex();
x = 1.0 / (b.r * b.r + b.i * b.i);
c.r = (a.r * b.r + a.i * b.i) * x;
c.i = (a.i * b.r - a.r * b.i) * x;
return c;
}
}