# 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: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Tests](https://img.shields.io/badge/tests-152%20assertions-brightgreen.svg)](#测试) [![Single File](https://img.shields.io/badge/产物-单文件%20584%20KB-blue.svg)](#快速开始) [![Runtime](https://img.shields.io/badge/运行-纯前端%20%2B%20Node%20测试-lightgrey.svg)](#目录结构) 木工吸尘器 / 集尘器接口的规格又杂又乱:设备口是 4 寸、软管是 2.5 寸、还要绕过机箱, 现成的转接头不是买不到就是尺寸不对。这个工具把"设计一个转接件"压缩成调几个滑块 —— 管径、壁厚、直管长度、弯折角度、管口防滑结构,都在浏览器里实时建模, 导出**水密、已摆正、Z 轴向上**的 STL,打开切片软件就能打印。 **没有后端、没有账号、不联网。** 构建产物是一个 584 KB 的自包含 HTML, 双击就能用,拷给别人也能用。 ![界面总览](docs/default-view.jpg) 默认场景: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。 ![单文件版](docs/standalone-preset.jpg) 拷给别人的就是这一个文件。点一下"常用规格"预设即可套用整套参数。 > 想自己构建出这个文件、或者改代码,看下面的「开发」。 ### 从源码跑起来 ```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 | 独立于凸缘;想让它骑在防脱环上就设成和凸缘一样 | ![摩擦凸点特写](docs/friction-nubs.jpg) 把管口单独做成一个短卡圈,就能看清一圈 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) 整理)。 ## 剖切视图 工具栏的「剖切」把靠近相机的一半切掉,可以直接看内腔;配合「线框」还能看清网格走向。 ![剖切视图](docs/cross-section.jpg) 直通变径 + 内侧摩擦凸点的剖切。可以清楚看到中段那段快速过渡的斜面,以及内壁上的一圈凸点。 ## 打印可用性检查 工具不只是画个形状,还会给出打印所需的判断: - **导出的 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,分发时请一并保留其许可声明。