aW1wb3J0IGphdmEuYXd0Lio7CmltcG9ydCBqYXZhLmF3dC5pbWFnZS4qOwppbXBvcnQgamF2YXguaW1hZ2Vpby4qOwppbXBvcnQgamF2YS5pby4qOwppbXBvcnQgamF2YS51dGlsLio7CmltcG9ydCBqYXZhLnV0aWwuZnVuY3Rpb24uKjsKCnB1YmxpYyBjbGFzcyBXYXZlZ3VpZGVQbG90IHsKCiAgICAvLyDkvaDnmoTlj4LmlbDvvJpFMjEgKFRNMjEpLCBhPTIzbW0sIGI9MTBtbSwgZj0zNkdIegogICAgc3RhdGljIGRvdWJsZSBhID0gMjNlLTM7CiAgICBzdGF0aWMgZG91YmxlIGIgPSAxMGUtMzsKICAgIHN0YXRpYyBkb3VibGUgZiA9IDM2ZTk7CiAgICBzdGF0aWMgZG91YmxlIGMgPSAzZTg7CiAgICBzdGF0aWMgZG91YmxlIG0gPSAyOyAgIC8vIFRNMjEg55qEIG0KICAgIHN0YXRpYyBkb3VibGUgbiA9IDE7ICAgLy8gVE0yMSDnmoQgbgoKICAgIHN0YXRpYyBkb3VibGUgZmMsIGxhbSwgbGFtX2csIGJldGEsIGtjLCBvbWVnYTsKICAgIHN0YXRpYyBmaW5hbCBkb3VibGUgZXBzMCA9IDguODU0ZS0xMjsKCiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB0aHJvd3MgSU9FeGNlcHRpb24gewogICAgICAgIC8vIDEuIOiuoeeul+W4uOaVsAogICAgICAgIGZjID0gYyAvIDIgKiBNYXRoLnNxcnQoTWF0aC5wb3cobSAvIGEsIDIpICsgTWF0aC5wb3cobiAvIGIsIDIpKTsKICAgICAgICBsYW0gPSBjIC8gZjsKICAgICAgICBsYW1fZyA9IGxhbSAvIE1hdGguc3FydCgxIC0gTWF0aC5wb3coZmMgLyBmLCAyKSk7CiAgICAgICAgYmV0YSA9IDIgKiBNYXRoLlBJIC8gbGFtX2c7CiAgICAgICAga2MgPSBNYXRoLlBJICogTWF0aC5zcXJ0KE1hdGgucG93KG0gLyBhLCAyKSArIE1hdGgucG93KG4gLyBiLCAyKSk7CiAgICAgICAgb21lZ2EgPSAyICogTWF0aC5QSSAqIGY7CgogICAgICAgIC8vIDIuIOaehOW7uiBIVE1MIOe9kemhte+8iOWGheW1jCBCYXNlNjQg5Zu+54mH77yJCiAgICAgICAgU3RyaW5nQnVpbGRlciBodG1sID0gbmV3IFN0cmluZ0J1aWxkZXIoKTsKICAgICAgICBodG1sLmFwcGVuZCgmcXVvdDsmbHQ7aHRtbCZndDsmbHQ7aGVhZCZndDsmbHQ7bWV0YSBjaGFyc2V0PSdVVEYtOCcmZ3Q7Jmx0O3RpdGxlJmd0O+azouWvvOWcuuWIhuW4g+WbviAoRTIxKSZsdDsvdGl0bGUmZ3Q7JnF1b3Q7KTsKICAgICAgICBodG1sLmFwcGVuZCgmcXVvdDsmbHQ7c3R5bGUmZ3Q7Ym9keXtmb250LWZhbWlseTpzYW5zLXNlcmlmO3RleHQtYWxpZ246Y2VudGVyO30gaW1ne21heC13aWR0aDoxMDAlO3dpZHRoOjQwMHB4O21hcmdpbjoxMHB4O2JvcmRlcjoxcHggc29saWQgI2NjYzt9Jmx0Oy9zdHlsZSZndDsmcXVvdDspOwogICAgICAgIGh0bWwuYXBwZW5kKCZxdW90OyZsdDsvaGVhZCZndDsmbHQ7Ym9keSZndDsmcXVvdDspOwogICAgICAgIGh0bWwuYXBwZW5kKCZxdW90OyZsdDtoMSZndDtFMjEgKFRNMjEpIOaooeWcuuWIhuW4g+WbviZsdDsvaDEmZ3Q7JnF1b3Q7KTsKICAgICAgICBodG1sLmFwcGVuZCgmcXVvdDsmbHQ7cCZndDvlj4LmlbDvvJphPTIzbW0sIGI9MTBtbSwgZj0zNkdIeiZsdDsvcCZndDsmcXVvdDspOwoKICAgICAgICAvLyAtLS0g5Lu75YqhM++8mnh5IOW5s+mdoiAoeiA9IDAsICZsYW1iZGE7LzgsICZsYW1iZGE7LzQsICZsYW1iZGE7LzIpIC0tLQogICAgICAgIGh0bWwuYXBwZW5kKCZxdW90OyZsdDtoMiZndDvku7vliqEz77yaeHkg5bmz6Z2i5aSn5bC65a+45Zy65YiG5biDICh8RXwpJmx0Oy9oMiZndDsmcXVvdDspOwogICAgICAgIGRvdWJsZVtdIHpWYWxzID0gezAsIGxhbSAvIDgsIGxhbSAvIDQsIGxhbSAvIDJ9OwogICAgICAgIGZvciAoZG91YmxlIHogOiB6VmFscykgewogICAgICAgICAgICBTdHJpbmcgZGF0YSA9IGdlbmVyYXRlSW1hZ2VEYXRhKDAsIGEsIDAsIGIsCiAgICAgICAgICAgICAgICAgICAgJnF1b3Q7eHksIHo9JnF1b3Q7ICsgU3RyaW5nLmZvcm1hdCgmcXVvdDslLjJmICZsYW1iZGE7JnF1b3Q7LCB6IC8gbGFtKSwKICAgICAgICAgICAgICAgICAgICAmcXVvdDt4IChtbSkmcXVvdDssICZxdW90O3kgKG1tKSZxdW90OywKICAgICAgICAgICAgICAgICAgICAoeCwgeSkgLSZndDsgZ2V0TWFnKHgsIHksIHopKTsKICAgICAgICAgICAgaHRtbC5hcHBlbmQoJnF1b3Q7Jmx0O2ltZyBzcmM9J2RhdGE6aW1hZ2UvcG5nO2Jhc2U2NCwmcXVvdDspLmFwcGVuZChkYXRhKS5hcHBlbmQoJnF1b3Q7JyZndDsmcXVvdDspOwogICAgICAgIH0KCiAgICAgICAgLy8gLS0tIOS7u+WKoTPvvJp4eiDlubPpnaIgKHkgPSAwLCBiLzgsIGIvNCwgYi8yKSAtLS0KICAgICAgICBodG1sLmFwcGVuZCgmcXVvdDsmbHQ7aDImZ3Q75Lu75YqhM++8mnh6IOW5s+mdouWkp+WwuuWvuOWcuuWIhuW4gyAofEV8KSZsdDsvaDImZ3Q7JnF1b3Q7KTsKICAgICAgICBkb3VibGVbXSB5VmFscyA9IHswLCBiIC8gOCwgYiAvIDQsIGIgLyAyfTsKICAgICAgICBmb3IgKGRvdWJsZSB5eSA6IHlWYWxzKSB7CiAgICAgICAgICAgIFN0cmluZyBkYXRhID0gZ2VuZXJhdGVJbWFnZURhdGEoMCwgYSwgMCwgbGFtIC8gMiwKICAgICAgICAgICAgICAgICAgICAmcXVvdDt4eiwgeT0mcXVvdDsgKyBTdHJpbmcuZm9ybWF0KCZxdW90OyUuMmYgYiZxdW90OywgeXkgLyBiKSwKICAgICAgICAgICAgICAgICAgICAmcXVvdDt4IChtbSkmcXVvdDssICZxdW90O3ogKG1tKSZxdW90OywKICAgICAgICAgICAgICAgICAgICAoeCwgeikgLSZndDsgZ2V0TWFnKHgsIHl5LCB6KSk7CiAgICAgICAgICAgIGh0bWwuYXBwZW5kKCZxdW90OyZsdDtpbWcgc3JjPSdkYXRhOmltYWdlL3BuZztiYXNlNjQsJnF1b3Q7KS5hcHBlbmQoZGF0YSkuYXBwZW5kKCZxdW90OycmZ3Q7JnF1b3Q7KTsKICAgICAgICB9CgogICAgICAgIC8vIC0tLSDku7vliqEz77yaenkg5bmz6Z2iICh4ID0gMCwgYS84LCBhLzQsIGEvMikgLS0tCiAgICAgICAgaHRtbC5hcHBlbmQoJnF1b3Q7Jmx0O2gyJmd0O+S7u+WKoTPvvJp6eSDlubPpnaLlpKflsLrlr7jlnLrliIbluIMgKHxFfCkmbHQ7L2gyJmd0OyZxdW90Oyk7CiAgICAgICAgZG91YmxlW10geFZhbHMgPSB7MCwgYSAvIDgsIGEgLyA0LCBhIC8gMn07CiAgICAgICAgZm9yIChkb3VibGUgeHggOiB4VmFscykgewogICAgICAgICAgICBTdHJpbmcgZGF0YSA9IGdlbmVyYXRlSW1hZ2VEYXRhKDAsIGIsIDAsIGxhbSAvIDIsCiAgICAgICAgICAgICAgICAgICAgJnF1b3Q7enksIHg9JnF1b3Q7ICsgU3RyaW5nLmZvcm1hdCgmcXVvdDslLjJmIGEmcXVvdDssIHh4IC8gYSksCiAgICAgICAgICAgICAgICAgICAgJnF1b3Q7eSAobW0pJnF1b3Q7LCAmcXVvdDt6IChtbSkmcXVvdDssCiAgICAgICAgICAgICAgICAgICAgKHksIHopIC0mZ3Q7IGdldE1hZyh4eCwgeSwgeikpOwogICAgICAgICAgICBodG1sLmFwcGVuZCgmcXVvdDsmbHQ7aW1nIHNyYz0nZGF0YTppbWFnZS9wbmc7YmFzZTY0LCZxdW90OykuYXBwZW5kKGRhdGEpLmFwcGVuZCgmcXVvdDsnJmd0OyZxdW90Oyk7CiAgICAgICAgfQoKICAgICAgICBodG1sLmFwcGVuZCgmcXVvdDsmbHQ7L2JvZHkmZ3Q7Jmx0Oy9odG1sJmd0OyZxdW90Oyk7CgogICAgICAgIC8vIDMuIOWGmeWFpeaWh+S7tiBvdXRwdXQuaHRtbAogICAgICAgIHRyeSAoRmlsZVdyaXRlciBmdyA9IG5ldyBGaWxlV3JpdGVyKCZxdW90O291dHB1dC5odG1sJnF1b3Q7KSkgewogICAgICAgICAgICBmdy53cml0ZShodG1sLnRvU3RyaW5nKCkpOwogICAgICAgIH0KICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oJnF1b3Q74pyFIOaIkOWKn+eUn+aIkCBvdXRwdXQuaHRtbO+8geivt+eUqOa1j+iniOWZqOaJk+W8gOafpeeci+aJgOacieWcuuWbvuOAgiZxdW90Oyk7CiAgICB9CgogICAgLy8g6K6h566X5oC75Zy65bmF5YC8IHxFfCA9IHNxcnQoRXgmc3VwMjsgKyBFeSZzdXAyOyArIEV6JnN1cDI7KQogICAgc3RhdGljIGRvdWJsZSBnZXRNYWcoZG91YmxlIHgsIGRvdWJsZSB5LCBkb3VibGUgeikgewogICAgICAgIGRvdWJsZSBzaW5fbSA9IE1hdGguc2luKG0gKiBNYXRoLlBJICogeCAvIGEpOwogICAgICAgIGRvdWJsZSBzaW5fbiA9IE1hdGguc2luKG4gKiBNYXRoLlBJICogeSAvIGIpOwogICAgICAgIGRvdWJsZSBjb3NfbSA9IE1hdGguY29zKG0gKiBNYXRoLlBJICogeCAvIGEpOwogICAgICAgIGRvdWJsZSBjb3NfbiA9IE1hdGguY29zKG4gKiBNYXRoLlBJICogeSAvIGIpOwogICAgICAgIGRvdWJsZSBFMCA9IDEuMDsKCiAgICAgICAgLy8g5a6e6YOo77yIdD0w5pe25Yi777yJCiAgICAgICAgZG91YmxlIEV6ID0gRTAgKiBzaW5fbSAqIHNpbl9uICogTWF0aC5jb3MoYmV0YSAqIHopOwogICAgICAgIGRvdWJsZSBjb2VmZl94ID0gLShiZXRhICogbSAqIE1hdGguUEkgLyBhKSAvIChrYyAqIGtjKSAqIEUwOwogICAgICAgIGRvdWJsZSBFeCA9IGNvZWZmX3ggKiBjb3NfbSAqIHNpbl9uICogKC1NYXRoLnNpbihiZXRhICogeikpOwogICAgICAgIGRvdWJsZSBjb2VmZl95ID0gLShiZXRhICogbiAqIE1hdGguUEkgLyBiKSAvIChrYyAqIGtjKSAqIEUwOwogICAgICAgIGRvdWJsZSBFeSA9IGNvZWZmX3kgKiBzaW5fbSAqIGNvc19uICogKC1NYXRoLnNpbihiZXRhICogeikpOwoKICAgICAgICByZXR1cm4gTWF0aC5zcXJ0KEV4ICogRXggKyBFeSAqIEV5ICsgRXogKiBFeik7CiAgICB9CgogICAgLy8g55Sf5oiQ5Y2V5byg54Ot5Yqb5Zu+77yM6L+U5ZueIEJhc2U2NCDlrZfnrKbkuLIKICAgIHN0YXRpYyBTdHJpbmcgZ2VuZXJhdGVJbWFnZURhdGEoZG91YmxlIHhtaW4sIGRvdWJsZSB4bWF4LCBkb3VibGUgeW1pbiwgZG91YmxlIHltYXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0cmluZyB0aXRsZSwgU3RyaW5nIHhsYWJlbCwgU3RyaW5nIHlsYWJlbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQmlGdW5jdGlvbiZsdDtEb3VibGUsIERvdWJsZSwgRG91YmxlJmd0OyBmaWVsZCkgdGhyb3dzIElPRXhjZXB0aW9uIHsKICAgICAgICBpbnQgVyA9IDQwMCwgSCA9IDMwMDsKICAgICAgICBCdWZmZXJlZEltYWdlIGltZyA9IG5ldyBCdWZmZXJlZEltYWdlKFcsIEgsIEJ1ZmZlcmVkSW1hZ2UuVFlQRV9JTlRfUkdCKTsKICAgICAgICBHcmFwaGljczJEIGcgPSBpbWcuY3JlYXRlR3JhcGhpY3MoKTsKCiAgICAgICAgLy8g55m96Imy6IOM5pmvCiAgICAgICAgZy5zZXRDb2xvcihDb2xvci5XSElURSk7CiAgICAgICAgZy5maWxsUmVjdCgwLCAwLCBXLCBIKTsKCiAgICAgICAgLy8g6K6h566X5omA5pyJ54K555qE5Zy65YC877yM5om+5pyA5aSn5YC8CiAgICAgICAgZG91YmxlIG1heFZhbCA9IDA7CiAgICAgICAgZG91YmxlW11bXSB2YWxzID0gbmV3IGRvdWJsZVtXXVtIXTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSAmbHQ7IFc7IGkrKykgewogICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiAmbHQ7IEg7IGorKykgewogICAgICAgICAgICAgICAgZG91YmxlIHggPSB4bWluICsgKHhtYXggLSB4bWluKSAqIGkgLyAoVyAtIDEpOwogICAgICAgICAgICAgICAgZG91YmxlIHkgPSB5bWluICsgKHltYXggLSB5bWluKSAqIChIIC0gMSAtIGopIC8gKEggLSAxKTsKICAgICAgICAgICAgICAgIGRvdWJsZSB2ID0gZmllbGQuYXBwbHkoeCwgeSk7CiAgICAgICAgICAgICAgICB2YWxzW2ldW2pdID0gdjsKICAgICAgICAgICAgICAgIGlmICh2ICZndDsgbWF4VmFsKSBtYXhWYWwgPSB2OwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyDnu5jliLbng63lipvlm77vvIhKZXQg6aKc6Imy5pig5bCE77yJCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgJmx0OyBXOyBpKyspIHsKICAgICAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogJmx0OyBIOyBqKyspIHsKICAgICAgICAgICAgICAgIGRvdWJsZSB2YWwgPSB2YWxzW2ldW2pdIC8gKG1heFZhbCArIDFlLTkpOwogICAgICAgICAgICAgICAgaWYgKERvdWJsZS5pc05hTih2YWwpKSB2YWwgPSAwOwogICAgICAgICAgICAgICAgaWYgKHZhbCAmbHQ7IDApIHZhbCA9IDA7CiAgICAgICAgICAgICAgICBpZiAodmFsICZndDsgMSkgdmFsID0gMTsKICAgICAgICAgICAgICAgIGltZy5zZXRSR0IoaSwgaiwgZ2V0SmV0Q29sb3IodmFsKSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIC8vIOe7mOWItui+ueahhuWSjOaWh+WtlwogICAgICAgIGcuc2V0Q29sb3IoQ29sb3IuQkxBQ0spOwogICAgICAgIGcuZHJhd1JlY3QoMjAsIDIwLCBXIC0gNDAsIEggLSA0MCk7CiAgICAgICAgZy5kcmF3U3RyaW5nKHRpdGxlLCAyNSwgMTUpOwogICAgICAgIGcuZHJhd1N0cmluZyh4bGFiZWwsIFcgLyAyIC0gMjAsIEggLSA1KTsKICAgICAgICBnLmRyYXdTdHJpbmcoeWxhYmVsLCA1LCBIIC8gMik7CiAgICAgICAgZy5kaXNwb3NlKCk7CgogICAgICAgIC8vIOi9rOS4uiBCYXNlNjQKICAgICAgICBCeXRlQXJyYXlPdXRwdXRTdHJlYW0gYmFvcyA9IG5ldyBCeXRlQXJyYXlPdXRwdXRTdHJlYW0oKTsKICAgICAgICBJbWFnZUlPLndyaXRlKGltZywgJnF1b3Q7cG5nJnF1b3Q7LCBiYW9zKTsKICAgICAgICBieXRlW10gYnl0ZXMgPSBiYW9zLnRvQnl0ZUFycmF5KCk7CiAgICAgICAgcmV0dXJuIEJhc2U2NC5nZXRFbmNvZGVyKCkuZW5jb2RlVG9TdHJpbmcoYnl0ZXMpOwogICAgfQoKICAgIC8vIEpldCDpopzoibLmmKDlsIQKICAgIHN0YXRpYyBpbnQgZ2V0SmV0Q29sb3IoZG91YmxlIHYpIHsKICAgICAgICBpbnQgciwgZywgYjsKICAgICAgICBpZiAodiAmbHQ7PSAwLjI1KSB7CiAgICAgICAgICAgIHIgPSAwOwogICAgICAgICAgICBnID0gKGludCkgKHYgKiA0ICogMjU1KTsKICAgICAgICAgICAgYiA9IDI1NTsKICAgICAgICB9IGVsc2UgaWYgKHYgJmx0Oz0gMC41KSB7CiAgICAgICAgICAgIHIgPSAwOwogICAgICAgICAgICBnID0gMjU1OwogICAgICAgICAgICBiID0gKGludCkgKCgxIC0gKHYgLSAwLjI1KSAqIDQpICogMjU1KTsKICAgICAgICB9IGVsc2UgaWYgKHYgJmx0Oz0gMC43NSkgewogICAgICAgICAgICByID0gKGludCkgKCh2IC0gMC41KSAqIDQgKiAyNTUpOwogICAgICAgICAgICBnID0gMjU1OwogICAgICAgICAgICBiID0gMDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByID0gMjU1OwogICAgICAgICAgICBnID0gKGludCkgKCgxIC0gKHYgLSAwLjc1KSAqIDQpICogMjU1KTsKICAgICAgICAgICAgYiA9IDA7CiAgICAgICAgfQogICAgICAgIHJldHVybiAociAmbHQ7Jmx0OyAxNikgfCAoZyAmbHQ7Jmx0OyA4KSB8IGI7CiAgICB9Cn0=
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;
import java.util.*;
import java.util.function.*;
public class WaveguidePlot {
// 你的参数:E21 (TM21), a=23mm, b=10mm, f=36GHz
static double a = 23e-3;
static double b = 10e-3;
static double f = 36e9;
static double c = 3e8;
static double m = 2; // TM21 的 m
static double n = 1; // TM21 的 n
static double fc, lam, lam_g, beta, kc, omega;
static final double eps0 = 8.854e-12;
public static void main(String[] args) throws IOException {
// 1. 计算常数
fc = c / 2 * Math.sqrt(Math.pow(m / a, 2) + Math.pow(n / b, 2));
lam = c / f;
lam_g = lam / Math.sqrt(1 - Math.pow(fc / f, 2));
beta = 2 * Math.PI / lam_g;
kc = Math.PI * Math.sqrt(Math.pow(m / a, 2) + Math.pow(n / b, 2));
omega = 2 * Math.PI * f;
// 2. 构建 HTML 网页(内嵌 Base64 图片)
StringBuilder html = new StringBuilder();
html.append("<html><head><meta charset='UTF-8'><title>波导场分布图 (E21)</title>");
html.append("<style>body{font-family:sans-serif;text-align:center;} img{max-width:100%;width:400px;margin:10px;border:1px solid #ccc;}</style>");
html.append("</head><body>");
html.append("<h1>E21 (TM21) 模场分布图</h1>");
html.append("<p>参数:a=23mm, b=10mm, f=36GHz</p>");
// --- 任务3:xy 平面 (z = 0, λ/8, λ/4, λ/2) ---
html.append("<h2>任务3:xy 平面大尺寸场分布 (|E|)</h2>");
double[] zVals = {0, lam / 8, lam / 4, lam / 2};
for (double z : zVals) {
String data = generateImageData(0, a, 0, b,
"xy, z=" + String.format("%.2f λ", z / lam),
"x (mm)", "y (mm)",
(x, y) -> getMag(x, y, z));
html.append("<img src='data:image/png;base64,").append(data).append("'>");
}
// --- 任务3:xz 平面 (y = 0, b/8, b/4, b/2) ---
html.append("<h2>任务3:xz 平面大尺寸场分布 (|E|)</h2>");
double[] yVals = {0, b / 8, b / 4, b / 2};
for (double yy : yVals) {
String data = generateImageData(0, a, 0, lam / 2,
"xz, y=" + String.format("%.2f b", yy / b),
"x (mm)", "z (mm)",
(x, z) -> getMag(x, yy, z));
html.append("<img src='data:image/png;base64,").append(data).append("'>");
}
// --- 任务3:zy 平面 (x = 0, a/8, a/4, a/2) ---
html.append("<h2>任务3:zy 平面大尺寸场分布 (|E|)</h2>");
double[] xVals = {0, a / 8, a / 4, a / 2};
for (double xx : xVals) {
String data = generateImageData(0, b, 0, lam / 2,
"zy, x=" + String.format("%.2f a", xx / a),
"y (mm)", "z (mm)",
(y, z) -> getMag(xx, y, z));
html.append("<img src='data:image/png;base64,").append(data).append("'>");
}
html.append("</body></html>");
// 3. 写入文件 output.html
try (FileWriter fw = new FileWriter("output.html")) {
fw.write(html.toString());
}
System.out.println("✅ 成功生成 output.html!请用浏览器打开查看所有场图。");
}
// 计算总场幅值 |E| = sqrt(Ex² + Ey² + Ez²)
static double getMag(double x, double y, double z) {
double sin_m = Math.sin(m * Math.PI * x / a);
double sin_n = Math.sin(n * Math.PI * y / b);
double cos_m = Math.cos(m * Math.PI * x / a);
double cos_n = Math.cos(n * Math.PI * y / b);
double E0 = 1.0;
// 实部(t=0时刻)
double Ez = E0 * sin_m * sin_n * Math.cos(beta * z);
double coeff_x = -(beta * m * Math.PI / a) / (kc * kc) * E0;
double Ex = coeff_x * cos_m * sin_n * (-Math.sin(beta * z));
double coeff_y = -(beta * n * Math.PI / b) / (kc * kc) * E0;
double Ey = coeff_y * sin_m * cos_n * (-Math.sin(beta * z));
return Math.sqrt(Ex * Ex + Ey * Ey + Ez * Ez);
}
// 生成单张热力图,返回 Base64 字符串
static String generateImageData(double xmin, double xmax, double ymin, double ymax,
String title, String xlabel, String ylabel,
BiFunction<Double, Double, Double> field) throws IOException {
int W = 400, H = 300;
BufferedImage img = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB);
Graphics2D g = img.createGraphics();
// 白色背景
g.setColor(Color.WHITE);
g.fillRect(0, 0, W, H);
// 计算所有点的场值,找最大值
double maxVal = 0;
double[][] vals = new double[W][H];
for (int i = 0; i < W; i++) {
for (int j = 0; j < H; j++) {
double x = xmin + (xmax - xmin) * i / (W - 1);
double y = ymin + (ymax - ymin) * (H - 1 - j) / (H - 1);
double v = field.apply(x, y);
vals[i][j] = v;
if (v > maxVal) maxVal = v;
}
}
// 绘制热力图(Jet 颜色映射)
for (int i = 0; i < W; i++) {
for (int j = 0; j < H; j++) {
double val = vals[i][j] / (maxVal + 1e-9);
if (Double.isNaN(val)) val = 0;
if (val < 0) val = 0;
if (val > 1) val = 1;
img.setRGB(i, j, getJetColor(val));
}
}
// 绘制边框和文字
g.setColor(Color.BLACK);
g.drawRect(20, 20, W - 40, H - 40);
g.drawString(title, 25, 15);
g.drawString(xlabel, W / 2 - 20, H - 5);
g.drawString(ylabel, 5, H / 2);
g.dispose();
// 转为 Base64
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "png", baos);
byte[] bytes = baos.toByteArray();
return Base64.getEncoder().encodeToString(bytes);
}
// Jet 颜色映射
static int getJetColor(double v) {
int r, g, b;
if (v <= 0.25) {
r = 0;
g = (int) (v * 4 * 255);
b = 255;
} else if (v <= 0.5) {
r = 0;
g = 255;
b = (int) ((1 - (v - 0.25) * 4) * 255);
} else if (v <= 0.75) {
r = (int) ((v - 0.5) * 4 * 255);
g = 255;
b = 0;
} else {
r = 255;
g = (int) ((1 - (v - 0.75) * 4) * 255);
b = 0;
}
return (r << 16) | (g << 8) | b;
}
}