Skip to content

四摇盖胶封盒几何(rectangular 族) ​

唯一几何真源:packages/dieline/src/rectangular.mjs。TypeScript 包装器 packages/dieline/src/boxes/rectangular.ts、 网页副本 docs/demo/assets/runtime/rectangular.mjs、Python 建稿脚本都用它 —— 由 tools/build-runtime.mjs 复制生成, 不要分别维护三份规则。

这是什么结构 ​

四侧板 + 上下各四摇盖 + 一个胶舌的胶封折叠纸盒(RSC 类),成型靠胶舌涂胶或胶带封口。 它不是磁吸灰板盒,也不是插舌锁底盒 —— 早期文档误标过,已在 docs/VERIFICATION-V1-V2.md 更正。

参数 ​

参数含义约束默认
width盒宽 W(front/right/back/left 中 front 的宽)0 < x ≤ 2000 mm必填
height盒高 H(侧板高)0 < x ≤ 2000 mm必填
depth盒深 D0 < x ≤ 2000 mm必填
glueMm胶舌宽 G0 < x ≤ 40 mm不一致,必须显式传:zod 包装器 10、rectangular.mjs 15
name盒型名(进 dielineId)≤80rectangular

展开公式 ​

text
摇盖高 flap = D / 2
展开宽   W  = 2 × (width + depth) + glueMm
展开高   H  = height + 2 × flap = height + depth

例:120 × 260 × 90、glueMm = 15 → flap = 45、435 × 350 mm(与 docs/DEMO.md 演示口径一致); 80 × 120 × 50、glueMm = 15 → flap = 25、275 × 170 mm、13 块面板(3D 预览与折叠测试用的就是这组)。

flap = D / 2 不只决定纸面高度,它还决定盒顶怎么闭合:前后摇盖各伸 D/2、横跨整个盒宽,在中线相遇把顶面 盖满;左右摇盖各伸 D/2 压在它们下面 → 顶面是"两端 doubleLayerMm = min(W, D) 双层 + 中间 singleLayerMm = max(0, W − D) 单层"的台阶,不是一条宽 = 宽 − 深的开口。 折不动时 deriveBox 会抛 四盖无法在中线闭合,而不是折出个漏顶的盒子。 完整口径与渲染层的共面处理见 摇盖闭合:双层台阶,不是开口。

实跑复现(零依赖,仓库根目录执行):

sh
node --input-type=module -e "
const m = await import('./packages/dieline/src/rectangular.mjs');
const g = m.rectangularGeometry({ width: 120, height: 260, depth: 90, glueMm: 15 });
console.log(g.sheetMm, g.panels.length, g.edges.length);
"
# → { width: 435, height: 350 } 13 35

面板布局(13 块,faceIndex 即生成顺序) ​

x 从 glueMm 起累加四侧板;侧板 y 范围 [flap, flap + H];顶盖贴顶边、底盖接在侧板下方。

faceIndexpanelIdrole120×260×90/G15 时的 x, y, w, h(mm)
0frontside15, 45, 120, 260
1front_toptop15, 0, 120, 45
2front_bottombottom15, 305, 120, 45
3rightside135, 45, 90, 260
4right_toptop135, 0, 90, 45
5right_bottombottom135, 305, 90, 45
6backside225, 45, 120, 260
7back_toptop225, 0, 120, 45
8back_bottombottom225, 305, 120, 45
9leftside345, 45, 90, 260
10left_toptop345, 0, 90, 45
11left_bottombottom345, 305, 90, 45
12glue_flapglue0, 45, 15, 260

线是怎么定出来的(不是手画的) ​

  1. 每块侧板先写两条横向折线:y = flap(顶)与 y = flap + H(底),加一条纵向折线在面板左边缘 x = 面板左边。 合计 12 条 crease(4 侧板 × 3)。
  2. 把这些折线的端点对(排序后取 key)放进 hinges 集合。
  3. 遍历 13 块面板的 4 条边:不在 hinges 里的边自动变成 cut,并用 Map 去重 → 22 条 cut。 所以相邻摇盖之间的切缝、摇盖外沿、胶舌外沿都是这套规则推导出来的,而不是逐条手写。
  4. 最后追加 1 条 glue:竖直线 x = glueMm / 2,上下各内缩 min(2, height / 4) mm (120×260×90/G15 → x = 7.5,从 y = 47 到 y = 303)。

edge 总数 = 22 cut + 12 crease + 1 glue = 35。types.ts 只要求 edges ≥ 4,具体数量由几何决定。

为什么四侧板自己没有 cut

front 的四条边(上折线、下折线、左右两条纵折线)都在 hinges 里,所以侧板不产出任何 cut —— 这正是"侧板被四周摇盖和折缝完全连接"的正确拓扑。想验证:改参数跑上面那条命令,再按 panelId 分组数一遍。

面板 ↔ UV 映射 ​

geometryMappings(g) 对每块面板取 bbox,产出 mappings:

text
dielineRectMm = bbox(panel)
uvRect        = { x/W, y/H, w/W, h/H }
faceIndex     = panel.faceIndex
uvRotateQuarter / mirrorU = 面板上的值(当前恒为 0 / false)

applyGeometry(design, params) 除写 mappings 外还会:

  • 把带 panelId 的图层按"面板旧 bbox → 新 bbox"平移 transform.x/y(改尺寸时内容跟着面板走);
  • 用 cut/crease/glue 重建三个 aux 引导层,并放在图层数组最前;
  • 用 sheetMm 覆盖 design.canvasMm,并回写 dieline.paramsMm(glueMm 缺省补 15)。

这就是本站点示例里 canvasMm 与 paramsMm 必须自洽的原因,check.mjs 会按公式回算一遍。

结构线之外的东西(都没有) ​

纸厚折放补偿、圆角半径、工艺缝隙、防尘翼(dust)、插舌(tuck)、锁底、异形刀线 —— 均未实现。 role 枚举预留了 tuck / dust,但生成器不会产出。归属见 能力边界。

交付前请核对文字、字体、结构与印厂要求,并保留确认版本。