// mathGraph.java import java.applet.Applet; import java.awt.*; import java.awt.event.*; public class mathGraph extends Applet implements ActionListener, ItemListener{ private int maxDim; // 次元最大値 private int width, height, dimension; // 横幅・縦幅・次元 private boolean flag; // 再描画の為のフラグ private CheckboxGroup cbg; // チェックボックス群 private Checkbox [] cb; private Label mes; // エラーメッセージ用ラベル private TextField byT; // 倍率 private TextField [] tfX; private Label [] lX; // dimensionによって大きさが変わる private TextField tfS; // y切片用テキストフィールド private Button submit, clear; // paint/clear ボタン public void init(){ /* * * * * * * * パラメータ受け取り&セット * * * * * * * */ int tmp = Integer.parseInt(getParameter("dimension")); maxDim = tmp >= 0 ? tmp : 4; int bg = Integer.parseInt(getParameter("bgcolor"), 16); int fontSize = Integer.parseInt(getParameter("fontSize")); String fontFamily = getParameter("family"); String fontBold = getParameter("font"); setLayout(new BorderLayout()); setBackground(new Color(bg)); if(fontBold.toLowerCase().equals("bold")) setFont(new Font(fontFamily, Font.BOLD, fontSize)); else if(fontBold.toLowerCase().equals("italic")) setFont(new Font(fontFamily, Font.ITALIC, fontSize)); else if(fontBold.toLowerCase().equals("bolditalic")) setFont(new Font(fontFamily, Font.BOLD+Font.ITALIC, fontSize)); else setFont(new Font(fontFamily, Font.PLAIN, fontSize)); /* * * * * * * * * * * * ここまで * * * * * * * * * * * * */ width = getSize().width; height = getSize().height; flag = false; // flag初期値はfalse dimension = maxDim; // dimensionの初期値は最大値 tfX = new TextField[dimension]; lX = new Label[dimension]; Panel byP = new Panel(new FlowLayout()); byP.add(new Label("倍率ドン!")); byP.add(byT = new TextField("10", 3)); byP.add(submit = new Button("更にドン!")); byP.add(clear = new Button("竹下さんに全部")); Panel p1 = new Panel(new FlowLayout()); p1.add(new Label("y =")); for(int i = dimension-1; i >= 0; i--){ tfX[i] = new TextField("1", 2); lX[i] = i != 0 ? new Label("x^" + Integer.toString(i+1) + " +") : new Label("x +"); p1.add(tfX[i]); p1.add(lX[i]); } p1.add(tfS = new TextField("0", 3)); Panel byP_p1 = new Panel(new GridLayout(2, 1)); byP_p1.add(byP); byP_p1.add(p1); cbg = new CheckboxGroup(); cb = new Checkbox[dimension]; Panel p3 = new Panel(new GridLayout(2, (int)Math.floor(dimension/2.0))); for(int i = 0; i < dimension; i++){ p3.add(cb[i] = new Checkbox(i+1+"次", cbg, true)); cb[i].addItemListener(this); // 次元の数だけCheckboxとリスナの追加 } Panel overPanel = new Panel(new FlowLayout()); overPanel.add(byP_p1); overPanel.add(p3); Panel underPanel = new Panel(new BorderLayout()); underPanel.add(mes = new Label()); Panel finPanel = new Panel(new BorderLayout()); finPanel.add(overPanel, BorderLayout.NORTH); finPanel.add(underPanel, BorderLayout.SOUTH); add(finPanel, BorderLayout.SOUTH); submit.addActionListener(this); clear.addActionListener(this); } public void paint(Graphics g){ mes.setText(""); int xZero = width / 2; // x軸の座標0 int yZero = height / 2; // y軸の座標0 if(!flag){ g.clearRect(0, 0, width, height); g.setColor(Color.black); g.drawString("(0, 0)", xZero-35, yZero+15); for(int i = -1; i <= 1; i++){ // 太くするため三回描画 g.drawLine(0, yZero+i, width, yZero+i); // x軸 g.drawLine(xZero+i, 0, xZero+i, height); // y軸 } } else{ double power = 1; try{ power = Math.abs(toDouble(byT.getText())); } // 倍率 catch(NumberFormatException e){ errorMes("Input must be 'Hankaku' numbers."); } if(power == 0) errorMes("Division by Zero."); double s = 0; try{ s = toDouble(tfS.getText()); } catch(NumberFormatException e){ errorMes("Input must be 'Hankaku' numbers."); } s *= power; // y切片取得 double [] x = new double[dimension]; // 次元に合った大きさに for(int i = 0; i < dimension; i++){ String tmp = tfX[i].getText(); try{ x[i] = tmp.equals("") ? 0 : toDouble(tmp); } catch(NumberFormatException e){ errorMes("Input must be 'Hankaku' numbers."); } } // それぞれの次元の係数を取得 double x1 = 65535, y1 = 65535; // あり得ない数字をフラグの代わりに double x2 = 0, y2 = 0; g.setColor(new Color((int)(Math.random() * 0xFFFFFF))); for(double i = 0-xZero; i <= xZero; i+=power){ // xの増加量はpower(power pixelを1単位とする) x2 = xZero + i; // xの増加量は一定 y2 = yZero - s; // まずy切片の計算 for(int j = dimension; j >= 1; j--){ double plus; if(j >= 2){ double beki = Math.pow(i/power, j)/Math.pow(power, j-2); plus = x[j-1] > 0 ? beki : 0 - beki; } else plus = x[j-1] > 0 ? i : 0 - i; y2 -= plus * Math.abs(x[j-1]); // これで y=(増加量×x)^次元+y切片 となる } if(x1 != 65535 && y1 != 65535 && y2 >= 0-height && y2 <= height*2){ // 座標が表示領域を大幅に超えていたりしたら描画しない g.drawLine((int)x1, (int)y1, (int)x2, (int)y2); try{ Thread.sleep(10); } catch(InterruptedException ie){ errorMes("割り込み発生?"); } } x1 = x2; y1 = y2; } } flag = false; } public void actionPerformed(ActionEvent e){ if(e.getActionCommand().equals("更にドン!")){ flag = true; repaint(); } else{ flag = false; repaint(); } } public void itemStateChanged(ItemEvent e){ for(int i = 1; i <= maxDim; i++){ // 何次方程式かを確かめて次元値に代入 if(((String)e.getItem()).equals(i+"次")){ dimension = i; break; } } for(int i = 0; i < maxDim; i++){ if(i < dimension){ tfX[i].setText("1"); tfX[i].setVisible(true); lX[i].setVisible(true); } else{ tfX[i].setText("0"); tfX[i].setVisible(false); lX[i].setVisible(false); } } } private double toDouble(String val){ return Double.valueOf(val).doubleValue(); } public void update(Graphics g){ paint(g); } private void errorMes(String s){ mes.setText("Error: " + s); throw new IllegalArgumentException("Error message sent. At errorMes."); } }