實現一個可視化函數曲線繪製元件,支援 sin(2x) + cos(3x) 波形繪製、座標軸渲染、滑鼠互動調整參數(原代碼為固定函數,本文擴展說明互動擴展點)。純 AWT/Swing 無外部依賴,適合科學計算視覺化入門。
import java.awt.*;
import javax.swing.*;
public class Func extends JFrame {
public static void main(String[] args) { new Func().update(); }
Func() {
super("Function Plotter");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setSize(310, 310);
setVisible(true);
}
public void update() { repaint(); }
// 目標函數:sin(2x) + cos(3x)
double f(double x) { return Math.sin(2*x) + Math.cos(3*x); }
public void paint(Graphics g) {
int w = getSize().width, h = getSize().height;
int hw = w/2, hh = h/2;
// 座標軸
g.drawLine(0, hh, w, hh); // X 軸
g.drawLine(hw, 0, hw, h); // Y 軸
// 標註
g.setColor(Color.RED);
g.drawString("0", hw+5, hh+12);
g.drawString("5.0", hw-20, 40);
g.drawString("5.0", w-20, hh+12);
g.setColor(Color.BLUE);
g.drawString("Sin[2x]+Cos[3x]", 10, 40);
// 繪製曲線
double max = 5.0; // 定義域 [-5, 5]
double xd = 2*max / w; // X 步長
double yd = hh / max; // Y 縮放
for (int px = 0; px < w-1; px++) {
double x0 = -max + px * xd;
double x1 = x0 + xd;
int y0 = hh - (int)(f(x0) * yd);
int y1 = hh - (int)(f(x1) * yd);
g.drawLine(px, y0, px+1, y1);
}
}
}
| 步驟 | 說明 |
|---|---|
| 定義域映射 | 螢幕 X 座標 [0, w] → 數學域 [-max, max],步長 xd = 2*max/w |
| 值域映射 | 函數值 [-max, max] → 螢幕 Y 座標 [hh, 0],縮放 yd = hh/max |
| 掃描線繪製 | 逐像素 X 計算函數值,連線形成連續曲線視覺 |
| Y 軸反向 | 螢幕座標 Y 向下增長,數學座標 Y 向上,需 hh - value |
// 新增欄位
double freq1 = 2, freq2 = 3; // sin(freq1*x) + cos(freq2*x)
double amp1 = 1, amp2 = 1;
// 修改 f(x)
double f(double x) { return amp1*Math.sin(freq1*x) + amp2*Math.cos(freq2*x); }
// 加入滑鼠監聽
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
// 水平拖曳調整 freq1,垂直調整 freq2
freq1 = 0.5 + e.getX() * 5.0 / getWidth();
freq2 = 0.5 + e.getY() * 5.0 / getHeight();
repaint();
}
});
// 加入滑鼠滾輪調整振幅
addMouseWheelListener(e -> {
amp1 *= e.getPreciseWheelRotation() < 0 ? 1.1 : 0.9;
repaint();
});
JPanel 覆寫 paintComponent(),setDoubleBuffered(true)。Graphics2D g2 = (Graphics2D)g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);BufferedImage 離屏渲染存檔 PNG/PDF。