# 3D打印管道生成器
**Repository Path**: liang_shaofei/3d-printed-pipe-generator
## Basic Information
- **Project Name**: 3D打印管道生成器
- **Description**: 参数化的除尘管道转接件生成器:自定义两端内壁管径、壁厚、直管段长度与弯折角度,可选在管口长卡管凸点(内侧 / 外侧),按材料给出收缩补偿,用 three.js 实时预览,并导出可以直接丢进切片软件的 STL(水密、已摆正、Z 轴向上)
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-09-19
- **Last Updated**: 2026-09-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 管道生成器 · 木工吸尘器转接
> 参数化的**除尘管道转接件**生成器:改几个数字,实时预览,导出一个可以直接丢进切片软件的 STL。
[](LICENSE)
[](#测试)
[](#快速开始)
[](#目录结构)
木工吸尘器 / 集尘器接口的规格又杂又乱:设备口是 4 寸、软管是 2.5 寸、还要绕过机箱,
现成的转接头不是买不到就是尺寸不对。这个工具把"设计一个转接件"压缩成调几个滑块 ——
管径、壁厚、直管长度、弯折角度、管口防滑结构,都在浏览器里实时建模,
导出**水密、已摆正、Z 轴向上**的 STL,打开切片软件就能打印。
**没有后端、没有账号、不联网。** 构建产物是一个 584 KB 的自包含 HTML,
双击就能用,拷给别人也能用。

默认场景:4" 转 2.5"、45° 弯头。左侧参数、右侧实时预览,右下角是模型尺寸 / 体积 / 质量 / 网格体检。
---
## 目录
- [能做什么](#能做什么)
- [快速开始](#快速开始)
- [使用说明](#使用说明)
- [参数手册](#参数手册)
- [剖切视图](#剖切视图)
- [打印可用性检查](#打印可用性检查)
- [技术实现](#技术实现)
- [目录结构](#目录结构)
- [开发](#开发)
- [测试](#测试)
- [常见问题](#常见问题)
- [贡献](#贡献)
- [许可](#许可)
---
## 能做什么
- **两端独立管径 + 恒定壁厚**:外壁 = 内壁 + 壁厚,单位统一 mm。
- **管径过渡**:两端先保持等径,只在中段一小段里快速变径(斜面 / 阶梯 / 全程渐变三种方式)。
- **弯折**:任意角度 `-180° ~ +180°`,自动取长半径弯头 `R = 1.5 × 外径`。
- **防脱凸缘**:管口一整圈的升余弦环,拦住软管防止整根滑脱。
- **摩擦凸点**:管口一圈若干个**独立小凸点**(可放内侧或外侧),靠摩擦防打滑 —— 易损件,磨平重打一个即可。
- **按材料收缩补偿**:PLA / PETG / ABS / ASA / TPU / 尼龙 各自的推荐放大值,导出时直接作用到坐标。
- **打印姿态自动求解**:枚举候选姿态算悬垂面积与贴台面积,挑"放得进幅面、支撑最少"的那个。
- **网格体检**:焊接顶点后逐边检查,确认是封闭流形才允许切片。
- **参数链接**:调好的配置压进 URL hash(`#p=...`),收藏或分享就能还原整套参数。
## 快速开始
### 只想用(不需要装任何东西)
下载 `dist/index.html`,**双击**。就这样 —— JS/CSS/three.js 全部内联在里面,
不需要服务器、不需要联网、不需要 Node。

拷给别人的就是这一个文件。点一下"常用规格"预设即可套用整套参数。
> 想自己构建出这个文件、或者改代码,看下面的「开发」。
### 从源码跑起来
```bash
git clone <你的仓库地址>
cd 管道生成器 # 仓库目录名
npm install # 只装两个东西:three(渲染)+ esbuild(打包)
npm run dev # 构建并启动本地预览 → http://127.0.0.1:5180/
```
| 命令 | 作用 |
| --- | --- |
| `npm run dev` | 构建 + 起本地静态服务(`http://127.0.0.1:5180/`) |
| `npm run build` | 只构建到 `dist/` |
| `npm test` | 89 项几何 / 摆放 / 导出校验,纯 Node,无需浏览器 |
| `npm run test:ui` | 63 项界面端到端(无头 Chrome/Edge,覆盖交互路径) |
### 产物说明
| 文件 | 说明 |
| --- | --- |
| `dist/index.html` | **主入口**。自包含单文件,双击即用,也可走 http 访问 |
| `dist/standalone.html` | 与 `dist/index.html` 字节相同,方便单独拷给别人 |
| `dist/app.js` | 未压缩 bundle,仅供调试阅读(页面**不**引用它) |
| `dist/style.css` | 样式源码,仅供调试阅读(页面**不**引用它) |
| `index.html`(根目录) | 入口导航页,双击后点「打开生成器」 |
| `src/template.html` | 构建模板,含 `__STYLE__` / `__SCRIPT__` 占位符,**直接打开会没有样式和脚本** |
---
## 使用说明
界面分两块:左边参数面板,右边 3D 预览。**预览即所得** —— 屏幕上看到的姿态和尺寸,
就是导出 STL 的内容。
1. 点一个**常用规格**预设(或者自己拖滑块)。
2. 从右上角提示区看工艺告警(壁厚偏薄、弯头太急、幅面超限……)。
3. 选好「打印摆放」和「材料」。
4. 点 **导出 STL**,丢进切片软件。
工具栏(左上):复位视角 / 正视 / 自动旋转 / 线框 / 剖切 / 标注 / 透视 / 复制参数链接 / 收起参数。
右侧面板显示模型尺寸、体积、质量、耗材长度、预估时长、网格体检结果。
**面板操作**
- **分组可折叠**:点任意分组标题(管径 / 壁厚、管径过渡、弯折……)即可收起或展开这一组,
标题左侧的小三角指示状态。折叠状态记在浏览器本地,刷新后保持。
- **一键收起**:工具栏的「收起参数」把 7 个分组全部折叠 / 全部展开,
小屏幕上想快速给 3D 视图腾地方时很好用。
- **恢复默认**:面板底部「恢复默认」清除当前全部配置并恢复出厂参数 ——
**会先弹确认框**,点「取消」或按 Esc 都不会改动任何东西。
确认后会一并清掉 URL 上的 `#p=` 参数与本地折叠偏好,刷新不会"复活"旧配置。
## 参数手册
### 管径 / 壁厚
| 参数 | 默认 | 说明 |
| --- | --- | --- |
| 入口内径 | 100 mm | 设备 / 集尘口一侧的内壁直径 |
| 出口内径 | 63 mm | 吸尘软管一侧的内壁直径 |
| 壁厚 | 3 mm | 恒定;FDM 建议 2~3mm,低于 1.2mm 会提示偏薄 |
### 管径过渡
| 参数 | 默认 | 说明 |
| --- | --- | --- |
| 过渡方式 | 斜面 | 斜面 = 中段圆锥快速过渡(推荐);阶梯 = 几级台阶;全程渐变 = 沿整根管慢慢收 |
| 过渡段长度 | 30 mm | 越短越紧凑,但斜面越陡、越可能需要支撑 |
| 过渡段位置 | 50 % | 沿中心线的位置,50% = 正中间 |
| 阶梯级数 | 3 | 仅「阶梯」模式;级数越多越接近斜面 |
### 直管段 / 弯折
| 参数 | 默认 | 说明 |
| --- | --- | --- |
| 入口直管长 | 45 mm | 插入设备端口的长度 |
| 出口直管长 | 70 mm | 套住软管的长度,建议 ≥ 40mm |
| 需要弯折 | 开 | 关闭即生成直通管 |
| 弯折角度 | 45° | `-180 ~ +180`,正负号决定向左 / 向右弯 |
| 自动弯折半径 | 开 | `R = 1.5 × 外径`(长半径弯头);关闭后可手填 |
### 防脱凸缘(bead)
管口**一整圈**的连续环,防止软管整根滑脱。
| 参数 | 默认 | 说明 |
| --- | --- | --- |
| 位置 | 无 | 无 / 入口 / 出口 / 两端 |
| 高度 | 2.5 mm | 凸出量 |
| 宽度 | 14 mm | 沿轴向的宽度,边缘用升余弦平滑过渡 |
| 距端面 | 8 mm | 近端离管口的距离 |
### 摩擦凸点(bump)
管口一圈**若干个独立小凸点**,靠摩擦防打滑。**和凸缘是两件不同的事**,参数互不影响。
| 参数 | 默认 | 说明 |
| --- | --- | --- |
| 位置 | 无 | 无 / 进口 / 出口 / 两端 |
| 内外侧 | 外侧 | 外侧 = 软管**套**上来被摩擦住;内侧 = 管件**插**进来被摩擦住 |
| 一圈几个 | 8 | 沿整圈均匀分布。摩擦点常用 6~12 个;改成 **1** 会变成一整圈卡筋 |
| 凸起高度 | 0.6 mm | 摩擦用 **0.4~0.8mm** 就够;超过 1.2mm 性质变成"卡扣",插拔会啃伤软管内壁 |
| 凸点直径 | 2.5 mm | **单个**凸点的直径(轴向同宽 → 小圆点);小于 1.5mm 0.4 喷嘴打不出来 |
| 凸点距端面 | 6 mm | 独立于凸缘;想让它骑在防脱环上就设成和凸缘一样 |

把管口单独做成一个短卡圈,就能看清一圈 8 个凸点长什么样;实际使用时它们长在转接管的管口上。
> **摩擦点是易损件。** 故意做小(一圈 8 个 ⌀2.5×0.6mm 只多用 **0.019%** 的料),
> 插拔多了会被磨平 —— 磨平了不影响使用,重新打一个就行,比磨坏整根转接管划算。
> 想更耐磨:高度加到 0.8~1mm、直径加到 3~4mm,或者用 PETG / 尼龙打印。
### 网格 / 打印
| 参数 | 默认 | 说明 |
| --- | --- | --- |
| 打印摆放 | 入口朝下 | 入口朝下 / 出口朝下 / 自动 / 最矮 / 原方向 |
| 打印机幅面 | 250 mm | 用于幅面检查,180~350mm |
| 材料 | PLA | 决定密度(算重量)与收缩补偿推荐值 |
| 按材料自动补偿 | 开 | 关掉后可手填实测值;有「恢复推荐值」按钮 |
| 缩放补偿 | 100.40 % | 导出时按比例放大,见下节 |
| 圆周分段 | 96 | 越大越圆,三角面数线性增长(24~256) |
### 收缩补偿参考值
FDM 件冷却后会缩,**配合尺寸**(插管、套软管)就差在这一点上。
补偿 = `1 / (1 - 收缩率)`,代码里由收缩率现算,不存在两处数字打架。
| 材料 | 已知收缩 | 推荐补偿 | 备注 |
| --- | --- | --- | --- |
| PLA | 0.40% | **100.40%** | 收缩很小、几乎各向同性,常温下尺寸最稳 |
| PETG | 0.60% | **100.60%** | 收缩小;大件容易翘边,腔温高时更接近 PLA |
| ABS | 1.15% | **101.16%** | 收缩大且各向异性,强烈建议封闭腔 + 按实测覆盖 |
| ASA | 0.55% | **100.55%** | 耐候版 ABS,收缩比 ABS 小 |
| TPU 柔性 | 0.50% | **100.50%** | 弹性体会回弹贴紧,配合尺寸可以放松一点 |
| 尼龙 PA | 1.37% | **101.39%** | 吸湿后还会继续涨,打印后建议先干燥再测 |
> ⚠️ **这些值是通用起点,不是保证值。** 实际收缩跟打印机、腔温、环境温度、填充率、
> 壁厚、走线速度都有关,同一卷料换台机器能差一倍。要精确配合:先打一个 50~100mm 的
> 方块或长条,量出实际尺寸 `s`,再把手填补偿设为 `100 / s`。
> 数据来源:[filament2print 的收缩与 warping 实测表](https://filament2print.com/gb/blog/136_warping-contractions-3D-printing-parts.html)
> (经 [STL_3Dprint_optimizer](https://github.com/H-Zeno/STL_3Dprint_optimizer/blob/main/material_scale_factors.yaml) 整理)。
## 剖切视图
工具栏的「剖切」把靠近相机的一半切掉,可以直接看内腔;配合「线框」还能看清网格走向。

直通变径 + 内侧摩擦凸点的剖切。可以清楚看到中段那段快速过渡的斜面,以及内壁上的一圈凸点。
## 打印可用性检查
工具不只是画个形状,还会给出打印所需的判断:
- **导出的 STL 已经摆正**:默认「入口朝下」,管口贴平台、模型最低点 z = 0、水平居中。
切片软件打开就是可打印姿态,不需要手动摆放。
- **自动摆放**:枚举「入口/出口朝下、包围盒三轴朝上」× 8 个自转角度,
用 45° 自支撑极限(面法线与竖直夹角 > 45°)算出**悬垂面积**,
优先选放得进幅面且支撑最少的姿态。
- **幅面检查**:超出所选打印机幅面直接告警。
- **贴台面积**:接近线接触时提示容易翘边 / 倾倒。
- **网格体检**:焊接顶点后检查每条有向边是否恰好被两个三角面反向共享,
确认是**封闭流形**才允许切片。
- **工艺提示**:壁厚过薄、弯头过急、过渡半锥角过大、最小内径偏小、
内侧凸点接近壁厚、凸点太密 / 太高(会自交)等都会给出建议。
---
## 技术实现
几何核心(`src/geometry.js`)**不依赖 three.js**,是纯数学实现,
所以能在 Node 里直接跑数值校验 —— 这是整个项目的测试策略能成立的前提。
### 中心线
单位统一 **mm**,弯折平面为 XY,截面圆对称于 `z = 0`。
中心线由三段组成:
```
入口直管段 ──→ 圆弧弯折段 ──→ 出口直管段
```
标架在弧长 `s` 处给出切向 `T`、弯折平面内法向 `N`、以及恒为 `(0,0,1)` 的 `B`。
### 管径过渡
内壁半径默认是"**两端等径 + 中段快速过渡**":`[0, transitionStart]` 与
`[transitionEnd, S]` 保持恒定管径,只有过渡段内才变化
—— 所以在过渡之前没有任何收缩或扩大,插软管时不会"越插越松"。
- `斜面`:过渡段内半径沿弧长线性变化(一段圆锥);
- `阶梯`:把这段圆锥换成 N 级台阶,用**同一弧长上的双环**表达立面
—— 零轴向长度、纯径向跳变,立面不贡献体积,网格依然逐边封闭(有解析解测试核对);
- `全程渐变`:沿整根管缓慢收缩。
### 摩擦凸点怎么融进网格
凸点是**管壁本身的径向位移**(角向 × 轴向两族升余弦包络),
而不是另加实心小块再做布尔合并:
- 整张网格依旧是**逐边封闭的曲面**,体积、流形体检、绕向自洽这些校验全部继续有效;
- 也不会出现"贴上去的疙瘩被切片软件当成独立壳体"的问题;
- 凸点所占的角度区间会被**单独加密采样**(峰值 / 半高 / 边界都打点),
否则包络比基准网格还窄时凸点会被采成一根尖刺 —— 实测高度精确等于设定值。
圆周采样是"基准均分 + 凸点角向节点"再按最小角距筛一遍,
所有站位共用同一套角度列表,因此环与环之间永远 1:1 连线 —— 这是凸点之后网格仍然封闭的关键。
### 姿态求解
`src/orient.js` 只做纯旋转 + 落台平移:枚举候选姿态 → 用低分辨率**探针网格**评估
悬垂面积 / 高度 / 贴台面积 → 挑最优 → 再作用到全分辨率网格上。
探针让候选枚举的代价与模型精度解耦。
### 数值自检
导出前用**散度定理**算有向体积,为正即代表绕向自洽;
测试里拿它和圆台解析解对比。
---
## 目录结构
```
src/geometry.js 几何核心:参数规范化 → 中心线标架 → 网格生成(含凸点位移场)
+ 体积/面积/包围盒/流形体检 + 材料表与收缩补偿推荐值
src/orient.js 打印摆放求解:3×3 旋转代数、候选姿态枚举、悬垂与贴台面积评估、落台
src/stl.js 导出器:二进制 STL(默认转 Z 轴向上)/ OBJ,支持分轴缩放
src/params.js 参数面板的单一数据源 + 预设 + URL 序列化 + 补偿取值
src/ui.js 按参数表生成控件(range / toggle / segment / select / action 按钮)
src/main.js three.js 场景、实时重建、HUD、工具栏、导出交互
src/style.css 界面样式
src/template.html 页面模板(构建时注入 JS/CSS,勿直接打开)
index.html 入口导航页
test/ geometry.test.mjs(65 项)、print.test.mjs(24 项)纯 Node;
ui.e2e.mjs(63 项)用无头浏览器跑真实产物,覆盖交互路径
build.mjs esbuild 打包 → dist/(自包含页面 + 调试用 bundle)
serve.mjs 零依赖静态服务器
```
源码 + 测试约 **4200 行**,运行期依赖只有 three.js 一个。
## 开发
```bash
npm install
npm run build # 改动后重新构建
node test/geometry.test.mjs # 只跑几何(改几何核心时最常用)
node test/print.test.mjs # 只跑摆放 / 导出测试
npm run test:ui # 界面端到端(需要本机有 Chrome 或 Edge)
```
改代码时的几个约定:
- **参数面板是数据驱动的**:新增一个可调参数,只在 `src/params.js` 的 `CONTROL_GROUPS`
里加一条,控件、显隐(`showIf`)、只读(`disabledIf`)、URL 序列化都会自动跟上。
- **几何核心不要引入 three.js**:它是能在 Node 里跑数值断言的前提。
- **改了网格生成就补解析解测试**:体积、凸起高度、角距这类量都有闭式解可对。
- 构建脚本会检查内联结果(占位符是否替换、`` 是否被截断),
改模板时别绕过这些断言。
## 测试
| 套件 | 项数 | 覆盖 |
| --- | --- | --- |
| `test/geometry.test.mjs` | 65 | 解析解体积、中心线/标架、流形与绕向、参数限幅、过渡、凸点几何、材料补偿 |
| `test/print.test.mjs` | 24 | 旋转矩阵代数、候选枚举、落台守恒、STL/OBJ 二进制布局与缩放 |
| `test/ui.e2e.mjs` | 63 | 真实产物里的滑块/开关/分段控件交互、分组折叠、恢复默认确认、HUD 联动、布局不溢出 |
合计 **152 项断言**,全部是纯 Node 或本机无头浏览器,不依赖网络。
其中不少是**解析解对照**而不是快照 —— 比如:
- 等径直管体积 = `π(Ro²-Ri²)L`;全程渐变锥壳 = 圆台解析解;
- 阶梯过渡的体积 = 各级圆柱之和(立面是零厚度圆环,不贡献体积);
- 竖直站立时贴台面积 = 环形端面面积 `π(Ro²-Ri²)`;
- 凸点峰值高度精确等于设定值,非凸点处严格等于标称外径。
## 常见问题
**打印相关**
- **壁厚怎么选**:FDM 建议 2~3mm(0.4 喷嘴 × 5~7 圈);低于 1.2mm 会提示偏薄。
- **要不要支撑**:竖着打印弯头时,弯折背面的悬垂超过 45° 就需要支撑;
换「出口朝下」或「自动」摆放常常可以免支撑。
- **配合太松 / 太紧**:先用「缩放补偿」微调,或把出口内径改 0.5mm 做间隙。
- **为什么两端是直筒**:默认只在中段过渡,入口/出口的插入段全长都是标称管径,
插软管或套设备口时不会"越插越松"。想让变径分摊到整根管就选「全程渐变」。
- **斜面还是阶梯**:斜面风阻小、推荐首选;阶梯更省料,但每级立面都是朝下的水平面,
竖着打印时留意方向(界面会给悬垂提示)。
**功能相关**
- **软管套上还是松**:先把外侧摩擦点加到 10~12 个、凸起升到 0.8mm;
还不够就加一圈防脱凸缘,或把数量设成 1 用整圈卡筋(那就属于"卡"而不是"摩擦"了)。
- **管件插不进去**:内侧凸点太高 / 太多,降到 0.8mm 左右并减到 4~6 个;
也可以适当放大出口内径(留 0.1~0.2mm 间隙)。
- **凸缘和摩擦点分不清**:凸缘是**一整圈连续的环**(管口那圈"腰线"),
摩擦点是**圆周上分开的一个个小圆点**。两个分组各自独立开关,互不影响。
- **内侧凸点看不见**:它长在空腔里,从外面当然看不到。用工具栏的「剖切」+「正视」,
或把相机转进管口;也可以用「线框」。
- **内侧凸点会把管壁打穿吗**:不会。程序只让它凸进空腔,并限制在壁厚的 80% 以内,
超了会告警;凸点背面的壁厚永远是正的(测试逐个顶点核对过)。
## 贡献
Issue 和 PR 都欢迎。提交前请确保:
1. `npm test` 与 `npm run test:ui` 全绿;
2. 改了行为就补对应测试(解析解优先于快照);
3. 中文注释 / 文案保持和现有风格一致。
有几个已知的改进方向,欢迎认领:
- [ ] **姿态求解性能**:`choosePlacement` 每次参数变更都做全分辨率复算,
400mm 的大件约 1.6s,拖滑块时有迟滞。可以改成防抖或挪进 Worker。
- [ ] **分轴收缩**:`meshToBinarySTL` / `meshToOBJ` 已支持 `xyScale` / `zScale`,
但界面还没暴露出来,目前只做了各向同性补偿。
- [ ] **更多接口特征**:螺纹、卡扣、O 型圈槽、法兰孔。
- [ ] **STEP / 3MF 导出**:目前只有 STL 和 OBJ。
- [ ] **英文界面**:文案集中在 `src/params.js` 和 `src/geometry.js`,抽出 i18n 不难。
## 许可
[MIT](LICENSE) © 2026 管道生成器 contributors
用到的第三方库:three.js(MIT)、esbuild(MIT)。
`dist/` 里的产物内联了 three.js,分发时请一并保留其许可声明。