AntennaSim
免费、开源的浏览器天线模拟器 —— 由 NEC2 驱动
试用在线演示 · docker run -p 80:80 ea1fuo/antennasim
17 种天线模板 ·
3D 辐射方向图 ·
SWR 与史密斯圆图 ·
导线编辑器 + 优化器 ·
NanoVNA 叠加层 ·
深色 / 浅色主题
从内置模板设计天线,或在导线编辑器中从零开始构建。运行 NEC2 仿真,在浏览器中即时可视化 SWR、阻抗、史密斯圆图、3D 辐射方向图、电流分布和近场热图。
**两种部署模式:** 使用 Docker 自托管(后端 + Redis)或通过 GitHub Pages 上的 WebAssembly 实现全静态 —— 无需服务器。
## 目录
- [功能特性](#features)
- [天线模板](#antenna-templates)
- [快速开始](#quick-start)
- [GitHub Pages (WebAssembly)](#github-pages-webassembly)
- [开发环境设置](#development-setup)
- [生产环境部署](#production-deployment)
- [系统架构](#architecture)
- [项目结构](#project-structure)
- [API 参考](#api-reference)
- [配置说明](#configuration)
- [键盘快捷键](#keyboard-shortcuts)
- [技术栈](#tech-stack)
- [贡献指南](#contributing)
- [许可证](#license)
- [致谢](#acknowledgments)
## 功能特性
仿真引擎
- **完整的 NEC2 流水线** —— 从几何定义到卡片组生成,再到 `nec2c` 执行和结果解析,全程自动化
- **频率扫描** —— 在任意频率范围内仿真,步长可配置
- **10 种地面模型** —— 自由空间、理想地面、海水、淡水、牧场、普通、岩石、城市、干/沙地以及自定义(用户定义介电常数和电导率)
- **集总负载** —— 串联 RLC、并联 RLC、固定阻抗以及导线导电率(铜、铝、钢、不锈钢)
- **传输线** —— 特性阻抗、长度、速度因子和并联导纳
- **GA/GM/GR 卡** —— 导线圆弧、坐标变换和圆柱对称性,用于复杂几何结构
- **Redis 缓存** —— 仿真结果使用 SHA-256 键和 zlib 压缩进行缓存(1 小时 TTL)
- **速率限制** —— 可选启用,可配置(默认:每小时 30 次,启用时每个 IP 5 个并发)
- **沙箱执行** —— `subprocess.run(shell=False, timeout=180)`,隔离的临时目录,非 root 容器
交互式 3D 视口
- **实时 3D 渲染** —— 使用轨道控制进行平移、旋转、缩放
- **辐射方向图** —— 具有感知均匀颜色映射的 3D 表面网格(增益单位 dBi)
- **体壳层** —— 替代性的多层外壳方向图可视化
- **电流分布** —— 导线段按电流幅度着色,使用热力图配色
- **动画电流流动** —— 发光粒子沿导线移动,速度与电流成正比
- **近场热图** —— E 场幅度显示为 3D 中的半透明平面
- **方向图切片** —— 扫过辐射方向图的动画切割平面
- **地面反射** —— 显示地面平面下方天线镜像的幽灵镜像
- **悬停测量** —— 光标悬停在任何 3D 对象上时,工具提示显示增益、导线尺寸、电流幅度或场强
- **自动取景** —— 加载和模板更改时,相机自动适应天线边界框
- **3D 方向控制器** —— 视口角落的交互式轴立方体;点击任意面/边/角可捕捉到该相机角度
- **罗盘玫瑰** 用于空间定向
图表与分析
- **SWR 与频率** —— 颜色编码区域(绿/黄/红)、业余频段标记、谐振标注、十字准线工具提示
- **阻抗 (R + jX)** —— 电阻和电抗曲线、参考阻抗线、jX=0 处的谐振交叉点
- **史密斯圆图** —— 带频率标记的阻抗轨迹、恒定 SWR 圆(1.5, 2.0, 3.0)、点击检查工具提示显示 Z、SWR 和反射系数
- **极坐标辐射方向图** —— 方位角(H 面)和仰角(E 面)切割、-3dB 波束宽度弧、最大增益标记、同心 dBi 网格
- **图表弹窗** —— 点击任意图表可扩展至全屏模态框以进行详细分析
- **图例** —— 每个图表都包含清晰的图例,解释所有颜色、线条和标记
- **Balun/Unun 匹配** —— 客户端阻抗变换,提供 10 种预设(1:1 至 49:1),用于查看相对于变换阻抗的 SWR
- **.s1p 叠加** —— 导入 NanoVNA 测量数据并叠加在仿真 SWR 上进行比较
导线编辑器
- **从零构建** —— 点击添加导线、拖动端点、对齐网格
- **移动模式** —— 拖动端点或整根导线;Shift+拖动仅限垂直移动
- **撤销/重做** —— 完整历史记录,使用 Ctrl+Z / Ctrl+Shift+Z
- **导线属性** —— 编辑坐标、半径、每根导线的段数
- **激励源** —— 设置具有幅度和相位的馈电点
- **负载与传输线** —— 在任意段上添加集总 RLC 负载和传输线模型
- **模板** —— 将任何内置模板加载到编辑器中并进行修改
- **导入/导出** —— 打开和保存 `.nec`(NEC2 卡片组)和 `.maa`(MMANA-GAL)文件
优化器
- **Nelder-Mead** 算法(scipy,自适应模式)
- **5 个目标函数** —— 最小化 SWR(单频)、最小化 SWR(频带平均)、最大化增益、最大化前后比、加权组合
- **最多 10 个变量**,具有最小/最大边界
- **实时进度** —— WebSocket 流式传输迭代计数、当前最佳 SWR、收敛图表
- **取消** —— 中途中止优化
其他
- **17 个天线模板**,涵盖导线、垂直、多频段、环形和定向类别
- **模板库页面** —— 浏览并比较所有模板,附带描述和难度评级
- **学习页面** —— 关于 NEC2、SWR、阻抗、辐射方向图和仿真技巧的教育内容
- **移动端响应式** —— 可在手机和平板电脑上使用,具有触摸友好的控件
- **深色/浅色主题** —— 系统感知,带手动切换
- **键盘快捷键** —— 17 个绑定用于快速工作流(按 `?` 查看全部)
## 天线模板
AntennaSim 附带 **17 个随时可仿真的模板**,按类别组织:
| 类别 | 模板 |
|---|---|
| **Wire(导线)** | 半波偶极子、倒 V、末端馈电半波 |
| **Vertical(垂直)** | 地平面垂直、J-Pole、Slim Jim |
| **Multiband(多频段)** | 偏心馈电偶极子、G5RV、扇形偶极子 |
| **Loop(环形)** | 三角环、水平三角环、立方体四方、小型磁环 |
| **Directional(定向)** | Yagi-Uda (2-6 单元)、Moxon 矩形、Hex Beam、对数周期偶极子阵列 |
每个模板都包含可配置参数(频率、高度、元件长度、间距、导线直径等),并提供合理的默认值和验证范围。
## 快速开始
### 前置条件
- [Docker](https://docs.docker.com/get-docker/) 和 [Docker Compose](https://docs.docker.com/compose/install/) (v2+)
- 就这些。不需要安装 Python、Node.js 或 nec2c。
### 一行命令
```
docker run -p 80:80 ea1fuo/antennasim
```
在浏览器中打开 **http://localhost**。完成。这将从 Docker Hub 拉取捆绑了所有内容(前端、后端、Redis、nginx)的一体化镜像。
### 从源码运行
```
git clone https://github.com/EA1FUO/AntennaSim.git
cd AntennaSim
cp .env.example .env
docker compose up --build
```
首次构建需要几分钟(下载基础镜像、编译 nec2c、安装依赖)。后续启动速度很快。
## GitHub Pages (WebAssembly)
AntennaSim 可以完全在浏览器中运行 —— 无需后端服务器。NEC2 引擎(`nec2c`)被编译为 WebAssembly,并在 Web Worker 中本地执行。
**在线演示:** https://EA1FUO.github.io/AntennaSim/
此模式通过在构建时设置 `VITE_ENGINE=wasm` 启用。GitHub Pages 部署通过 `deploy-pages.yml` 工作流完全自动化,该工作流:
1. 检出包含 `nec2c` git 子模块的仓库
2. 使用 Emscripten 将 nec2c 编译为 WebAssembly
3. 使用 `VITE_ENGINE=wasm` 构建前端
4. 部署到 GitHub Pages
两种部署模式(Docker 和 WASM)在功能上是等效的 —— 相同的仿真引擎、相同的 UI、相同的结果。
| | Docker | WebAssembly |
|---|---|---|
| **需要服务器** | 是 | 否 |
| **仿真运行于** | 后端 (Python + nec2c) | 浏览器 (Web Worker + WASM) |
| **缓存** | Redis | 无 |
| **优化器** | 后端 | 浏览器 (TypeScript Nelder-Mead) |
| **速率限制** | 可配置 | 不适用 |
| **适用于** | 自托管 / 多用户 | 静态托管 / 演示 |
## 开发环境设置
对于前端和后端都启用了热重载的活跃开发:
```
# 克隆 (--recursive 会获取用于 WASM 构建的 nec2c 子模块)
git clone --recursive https://github.com/EA1FUO/AntennaSim.git
cd AntennaSim
cp .env.example .env
# 使用 base + dev 覆盖启动(行为与 ./scripts/dev.sh 相同)
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
```
或者使用开发脚本:
```
./scripts/dev.sh
```
| 服务 | URL | 热重载 |
|---|---|---|
| Frontend(前端) | http://localhost:5173 | 是 |
| Backend API(后端 API) | http://localhost:8000 | 是 (Uvicorn --reload) |
| API Docs (Swagger) | http://localhost:8000/docs | -- |
| Redis | localhost:6379 | -- |
源目录通过卷挂载,因此更改会立即反映:
- `frontend/src/` —— React 组件、页面、store
- `backend/src/` —— FastAPI 端点、仿真运行器、解析器
### 本地 WASM 开发
要在本地运行 WASM 引擎(无需 Docker):
```
git clone --recursive https://github.com/EA1FUO/AntennaSim.git
cd AntennaSim
# 将 nec2c 构建为 WebAssembly(需要 Emscripten SDK)
cd wasm && ./build.sh && cd ..
cp wasm/build/nec2c.js wasm/build/nec2c.wasm frontend/public/wasm/
# 在前端以 WASM 模式启动
cd frontend
npm install
npm run dev:wasm
```
## 生产环境部署
### Docker Compose(推荐)
```
# 在您的 VPS/服务器上:
git clone https://github.com/EA1FUO/AntennaSim.git
cd AntennaSim
cp .env.example .env
# 编辑 .env 用于生产环境:
# - 设置 ENVIRONMENT=production
# - 设置 ALLOWED_ORIGINS 为您的域名
# - 根据需要调整资源限制
docker compose up -d --build
```
生产堆栈包括:
- **nginx** 反向代理,监听 80/443 端口,具有 gzip、安全标头和 WebSocket 支持
- **Frontend(前端)** 作为静态文件提供(Vite 构建)
- **Backend(后端)** 具有资源限制(2 CPU,512MB RAM)、只读文件系统、`no-new-privileges`
- **Redis** 具有 128MB LRU 缓存
### SSL/HTTPS
nginx 配置已为 SSL 准备就绪。要启用:
1. 获取证书(例如通过 [Certbot](https://certbot.eff.org/) / Let's Encrypt)
2. 将证书挂载到 nginx 容器中
3. 在 `nginx/nginx.conf` 中取消注释 SSL 服务器块
4. 在 `docker-compose.yml` 中设置 443 端口
### 资源需求
| 资源 | 最低 | 推荐 |
|---|---|---|
| CPU 1 核心 | 2+ 核心 |
| RAM | 512 MB | 1 GB |
| Disk(磁盘) | 500 MB | 1 GB |
| OS(操作系统) | 任何支持 Docker 的系统 | Linux (amd64) |
## 系统架构
```
+----------+
| Browser |
+----+-----+
|
HTTP / WS
|
+---------+---------+
| nginx |
| reverse proxy |
| :80 / :443 |
+---------+---------+
/ \
/ \
+--------+--+ +-----+------+
| Frontend | | Backend |
| React SPA | | FastAPI |
| :80 (prod)| | :8000 |
| :5173(dev)| +-----+------+
+-----------+ |
| +--------+
+----+ Redis |
| | :6379 |
| +--------+
|
+----+----+
| nec2c |
| engine |
+---------+
```
**数据流:** 用户在浏览器中配置天线 -> React 生成 NEC2 卡片组 -> POST 到 FastAPI -> 后端写入 `.nec` 文件,运行 `nec2c` 子进程 -> 输出解析为结构化 JSON -> 结果在 Redis 中缓存 -> 响应发送到前端 -> 图表和 3D 视口更新。
**数据流:** 相同的前端,但仿真在本地运行:React 生成卡片组 -> Web Worker 写入 WASM 虚拟文件系统 -> `nec2c.wasm` 执行 -> TypeScript 解析器提取结果 -> 图表和 3D 视口更新。无网络请求。
## 项目结构
```
AntennaSim/
|-- frontend/ # React 19 + TypeScript + Vite
| |-- src/
| | |-- components/
| | | |-- three/ # 3D viewport (R3F): antenna, pattern, current, NF, raycaster
| | | |-- editors/ # Template parameter editor, wire editor, balun editor
| | | |-- results/ # Charts: SWR, impedance, Smith, polar, gain table
| | | |-- ui/ # Reusable primitives: tabs, modals, chart popups
| | | |-- layout/ # App shell, panels, responsive wrappers
| | | +-- common/ # Shared utilities, keyboard shortcuts
| | |-- hooks/ # Custom hooks (chart theme, debounce, etc.)
| | |-- stores/ # Zustand stores (antenna, simulation, editor, UI, compare)
| | |-- templates/ # 17 antenna template definitions
| | |-- engine/ # Simulation engine abstraction (backend + WASM)
| | | |-- backend/ # BackendEngine: REST API + WebSocket
| | | |-- wasm/ # WasmEngine: Web Workers + nec2c.wasm
| | | |-- parsers/ # TypeScript ports of NEC2 input/output parsers
| | | +-- optimizer/ # TypeScript Nelder-Mead optimizer
| | |-- utils/ # Units, formatting, .s1p parser, matching
| | |-- pages/ # Route pages (Simulator, Editor, Library, Learn, About)
| | +-- api/ # API client (fetch + WebSocket)
| |-- Dockerfile # Production: multi-stage build -> nginx static
| +-- Dockerfile.dev # Development: Vite dev server with HMR
|
|-- backend/ # Python 3.12 + FastAPI
| |-- src/
| | |-- api/v1/ # REST + WebSocket endpoints
| | |-- simulation/ # NEC runner, output parser, optimizer, cache
| | |-- models/ # Pydantic models (antenna, simulation, results)
| | +-- converters/ # .maa / .nec import and export
| |-- Dockerfile # Production: python:3.12-slim + nec2c
| +-- Dockerfile.dev # Development: uvicorn --reload
|
|-- nginx/ # Reverse proxy
| |-- nginx.conf # Proxy rules, gzip, security headers, WebSocket
| +-- Dockerfile # nginx:alpine
|
|-- deploy/
| +-- allinone/ # All-in-one Docker image support files
| |-- supervisord.conf # Manages redis, uvicorn, nginx processes
| +-- nginx.conf # Serves frontend + proxies /api/ to uvicorn
|
|-- wasm/ # WebAssembly build infrastructure
| |-- nec2c/ # nec2c git submodule (KJ7LNW/nec2c)
| |-- patches/ # Emscripten compatibility patches
| |-- CMakeLists.txt # Emscripten build config
| +-- build.sh # Build script (emcmake + emmake)
|
|-- .github/workflows/
| |-- ci.yml # Lint, type-check, build on PRs and pushes to main
| |-- pr-title.yml # Validates Conventional Commits format on PR titles
| |-- docker-publish.yml # Builds and pushes Docker images on version tags
| +-- deploy-pages.yml # Build WASM + deploy to GitHub Pages
|
|-- scripts/
| +-- dev.sh # Start development environment
|
|-- VERSION # Single source of truth for app version (e.g. 0.6.0)
|-- Dockerfile # All-in-one image: frontend + backend + redis + nginx
|-- docker-compose.yml # Production stack (4 services)
|-- docker-compose.dev.yml # Development overrides (hot-reload, exposed ports)
|-- .env.example # Environment variable template
|-- LICENSE # GPL-3.0
+-- README.md # You are here
```
## API 参考
所有端点都在 `/api/v1/` 下。后端运行时可在 `/docs` 访问交互式 Swagger 文档。
### `POST /api/v1/simulate`
运行 NEC2 仿真。
**请求体:**
```
{
"wires": [
{ "tag": 1, "segments": 21, "x1": 0, "y1": -5.05, "z1": 10,
"x2": 0, "y2": 5.05, "z2": 10, "radius": 0.001 }
],
"excitations": [
{ "wire_tag": 1, "segment": 11, "real": 1.0, "imag": 0.0 }
],
"ground": { "type": "average" },
"frequency": { "start_mhz": 13.5, "end_mhz": 15.0, "steps": 31 },
"compute_currents": true,
"near_field": {
"enabled": true,
"plane": "horizontal",
"height_m": 1.8,
"extent_m": 20,
"resolution_m": 0.5
}
}
```
**响应:** 完整的仿真结果,包括每个频率点的阻抗、SWR、增益、辐射方向图、每段电流和近场数据。
### `POST /api/v1/optimize`
运行参数优化(同步)。
### `WebSocket /api/v1/ws/optimize`
实时优化器进度流。发送带有迭代编号、当前最佳 SWR、参数值和收敛状态的 JSON 帧。
### `POST /api/v1/convert/import`
从 `.maa` 或 `.nec` 文件导入天线定义。将文件作为表单数据上传,接收结构化 JSON。
### `POST /api/v1/convert/export`
将天线数据导出为 `.maa` 或 `.nec` 格式。发送 JSON,接收文件。
### `GET /api/v1/health`
健康检查。返回 nec2c 可用性、Redis 状态、应用版本和环境。
## 配置说明
将 `.env.example` 复制到 `.env` 并调整:
```
# Backend
ENVIRONMENT=development # development | production
ALLOWED_ORIGINS=http://localhost:5173 # CORS origins (comma-separated)
REDIS_URL=redis://redis:6379 # Redis connection
LOG_LEVEL=debug # debug | info | warning | error
SIM_TIMEOUT_SECONDS=180 # Per-simulation timeout (seconds)
NEC_WORKDIR=/tmp/nec_workdir # Temp directory for .nec files
# Rate limiting(可选,默认禁用)
RATE_LIMIT_ENABLED=false # Set to true for public deployments
RATE_LIMIT_PER_HOUR=30 # Max simulations per IP per hour
MAX_CONCURRENT_PER_IP=5 # Max concurrent simulations per IP
# Frontend (Vite)
VITE_API_URL=http://localhost:8000 # Backend URL
VITE_WS_URL=ws://localhost:8000 # WebSocket URL
# VITE_ENGINE=backend # "backend" (默认) 或 "wasm" (GitHub Pages)
```
## 键盘快捷键
在应用任意位置按 `?` 查看完整的快捷键面板。
### 模拟器
| 按键 | 操作 |
|---|---|
| `Ctrl + Enter` | 运行仿真 |
| `Scroll`(滚动) | 缩放 |
| `Left drag`(左键拖动) | 旋转 |
| `Right drag`(右键拖动) | 平移 |
### 导线编辑器
| 按键 | 操作 |
|---|---|
| `V` | 选择模式 |
| `A` | 添加导线模式 |
| `M` | 移动模式 |
| `Ctrl + Z` | 撤销 |
| `Ctrl + Shift + Z` | 重做 |
| `Ctrl + A` | 全选 |
| `Delete` | 删除选中项 |
| `Escape` | 取消全选 |
## 技术栈
### Frontend(前端)
| 技术 | 版本 | 用途 |
|---|---|---|
| [React](https://react.dev) | 19 | UI 框架 |
| [TypeScript](https://www.typescriptlang.org) | 5.9 | 类型安全(严格模式) |
| [Vite](https://vite.dev) | 7 | 具有 HMR 的构建工具 |
| [Tailwind CSS](https://tailwindcss.com) | 4 | 实用优先的样式 |
| [React Three Fiber](https://r3f.docs.pmnd.rs) | 9.5 | 声明式 Three.js |
| [Three.js](https://threejs.org) | 0.183 | 3D 渲染引擎 |
| [Zustand](https://zustand.docs.pmnd.rs) | 5.0 | 状态管理 |
| [Recharts](https://recharts.org) | 3.7 | 图表库 |
### Backend(后端)
| 技术 | 版本 | 用途 |
|---|---|---|
| [Python](https://python.org) | 3.12 | 运行时 |
| [FastAPI](https://fastapi.tiangolo.com) | 0.115+ | Web 框架 |
| [Pydantic](https://docs.pydantic.dev) | 2.10+ | 数据验证 |
| [nec2c](https://www.pa3fwm.nl/software/nec2c/) | -- | NEC2 引擎(C 移植版) |
| [SciPy](https://scipy.org) | 1.14+ | Nelder-Mead 优化器 |
| [Redis](https://redis.io) | 7 | 结果缓存 |
### Infrastructure(基础设施)
| 技术 | 用途 |
|---|---|
| [Docker](https://docker.com) | 容器化 |
| [Docker Compose](https://docs.docker.com/compose/) | 多服务编排 |
| [nginx](https://nginx.org) | 反向代理、SSL 终结、安全标头 |
## 贡献指南
欢迎贡献。这是一个面向业余无线电社区的免费开源项目。
### 如何贡献
1. **Fork** 本仓库
2. 为你的功能或修复 **创建一个分支** (`git checkout -b feat/my-feature`)
3. **进行更改** —— 遵循现有代码风格
4. **测试** —— 在 `frontend/` 中运行 `npx tsc --noEmit && npx vite build` 进行验证
5. 使用 [约定式提交](https://www.conventionalcommits.org/) **提交**:`feat:`、`fix:`、`perf:`、`docs:`、`refactor:`
6. **打开 Pull Request**,清晰描述内容和原因
### 准则
- TypeScript `strict: true` —— 禁止使用 `any` 类型
- 所有 R3F 组件中使用 `useMemo` / `useCallback` —— 渲染循环中不得分配内存
- 所有后端输入使用 Pydantic 验证,带 `Field(ge=..., le=...)`
- `subprocess.run(shell=False, timeout=30)` —— 始终如此
- 移动端响应式:在 375px、768px、1024px、1440px 下测试
- 除非绝对必要,否则不要添加依赖项
### 报告 Bug
打开一个 [Issue](https://github.com/EA1FUO/AntennaSim/issues) 并附带:
- 预期发生的情况 vs 实际发生的情况
- 浏览器、操作系统和设备
- 重现步骤
- 如有控制台错误
### 想法与功能请求
打开一个 [讨论](https://github.com/EA1FUO/AntennaSim/discussions) —— 我们很乐意听听哪些天线、功能或改进对您最有用。
## 许可证
AntennaSim 是根据 [GNU 通用公共许可证 v3.0](LICENSE) 发布的自由软件。
```
Copyright (C) 2025 AntennaSim Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
```
您可以自由使用、修改和分发本软件。如果您分发修改版本,它们也必须在 GPL-3.0 下发布。有关全文,请参阅 [LICENSE](LICENSE)。
## 致谢
- **[NEC2](https://en.wikipedia.org/wiki/Numerical_Electromagnetics_Code)** —— 由劳伦斯利弗莫尔国家实验室开发的数值电磁代码。数十年来天线仿真的基础。
- **[nec2c](https://www.pa3fwm.nl/software/nec2c/)** —— 由 Neoklis Kyriazis (5B4AZ) 进行的 NEC2 C 语言翻译版,使 NEC2 在现代系统上可用。
- **业余无线电社区** —— 感谢数十年的天线设计知识、实验和分享。
由业余无线电操作员为业余无线电操作员构建。
73 de AntennaSim