Skip to main content

家具布局系统 - 三种模式对比流程文档

整体架构

┌─────────────────────────────────────────────────────────────────────┐  
│ AI 对话阶段(共用) │
│ Round 1: 选择 SolverType → Round 2: 生成 L2 List + Relationships │
└─────────────────────────────────────────────────────────────────────┘

┌────────────────────┬────────────────────┐
↓ ↓ ↓
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ 模式 1 │ │ 模式 2 │ │ 模式 3 │
│ 用户SolverType │ │ LLM SolverType │ │ LLM SolverType │
│ + 模板Relations │ │ + 模板Relations │ │ + LLM Relations│
└────────────────┘ └────────────────┘ └────────────────┘
↓ ↓ ↓
└────────────────────┴────────────────────┘

Constraint Solver(共用)

Canvas 渲染展示

第一部分:AI 对话阶段(三种模式共用)

1.1 Round 1:选择布局拓扑类型(SolverType)

输入

字段说明示例
L1 区域类型L1Typesofa_group
L1 边界尺寸宽 L × 深 D (mm)4000 × 3000
朝向 facingDir面向方向向量[0, 0, -1]
靠墙 wallAttach靠墙方向back / left / right / 无
风格 style设计风格意式极简
关键词 keywords用户描述关键词["贵妃榻", "简约"]
mustHave必须包含的家具["COFFEE_TABLE"]
mustNotHave排除的家具["FLOOR_LAMP"]

6 种拓扑类型

SolverType适用场景关联风格
Linear_I_Shape窄长空间、紧凑布局现代简约、北欧
Corner_L_ShapeL型沙发/贵妃榻组合意式极简、现代轻奢
Parallel_Facing对称正式、社交会客中式、法式、新古典、美式
U_Shape_Enclosed围合会客、多座位中式、新中式、美式、欧式
Organic_Curved异形/弧线造型侘寂、日式极简、有机现代
Omni_Modular_Island四面不靠墙、中央布局后现代、开放式

选择规则(按优先级从高到低)

  1. 用户明确指定拓扑 → 直接使用

    • "U型"/"围合" → U_Shape_Enclosed
    • "L型"/"贵妃榻"/"转角" → Corner_L_Shape
    • "一字"/"直排" → Linear_I_Shape
    • "对坐"/"面对面" → Parallel_Facing
    • "弧形"/"曲线" → Organic_Curved
    • "岛式"/"中央" → Omni_Modular_Island
  2. 风格匹配 → 按"关联风格"列选择最匹配的拓扑

  3. 空间特征辅助判断(不覆盖规则 1、2)

    • 无靠墙 → 倾向 Omni_Modular_Island
    • 窄长空间 → 倾向 Linear_I_Shape

输出

{  
"solverType": "Corner_L_Shape",
"reasoning": "用户提及贵妃榻,匹配L型转角布局"
}

1.2 Round 2:生成 L2 家具列表 + Relationships

输入

  • Round 1 确定的 solverType
  • L1 尺寸、用户意图
  • 可用家具目录(从 L1_TYPE_CONFIGS 动态生成)
  • 家具尺寸参考表(从黄金样本统计,按 solverType 分类)

关系类型定义

type含义参数
FRONT_OFA 在 B 正前方(-y方向)distance
BESIDEA 在 B 旁边(横向)side (left/right), distance
PERPENDICULAR_ATTACHA 垂直接合 B 端部(旋转90°)attachSide, gap
UNDERz轴层叠,俯视图中心对齐
FACINGA 面对 B(旋转180°)distance
CORNERA 在角落位置distance
CENTER_OFA 居中于 B

间距参考

关系类型建议间距
FRONT_OF350-600mm
BESIDE0-150mm
FACING≥1200mm

空间约束规则

  • 横向(X轴):同一 BESIDE 链上所有家具的 L + 间距之和 ≤ L1.L
  • 纵向(Y轴):同一 FRONT_OF 链上所有家具的 D + 间距之和 ≤ L1.D
  • 防重叠:禁止多个 BESIDE 关系指向同一目标的同一 side,必须用链式关系(A→B→C)代替并排指向(A→B, C→B 同侧)
  • 空间不足时:缩小家具尺寸或减少数量

Tool 调用流程(check_space

1. LLM 草拟 l2List + relationships  
2. 调用 check_space 校验
3. 有 conflicts → 按 suggestions 调整 → 重新调用
4. 无 conflicts → 输出最终结果

check_space Tool 详情

输入

{  
l1BoundingBox: { L: number, D: number },
l2List: Array<{
role: string,
typeTag: string,
boxSize: { L: number, D: number }
}>,
relationships?: Array<{
from: string,
to: string,
type: string,
distance?: number,
side?: string
}>
}

校验内容

校验项约束类型阈值/条件
单件尺寸超出 L1硬约束任一维度超出即报错
单件面积占比软约束> 40% 警告
总利用率混合50-60% 警告, >60% 硬约束
BESIDE 横向链总宽硬约束> L1.L 报错
FRONT_OF 纵向链总深硬约束> L1.D 报错

输出

{  
l1Area: number, // L1 总面积 mm²
totalL2Area: number, // L2 总面积(排除 FABRIC)
utilization: "45%", // 利用率
conflicts: string[], // 硬约束冲突(必须修)
warnings: string[], // 软约束警告(建议修)
suggestions: string[] // 具体调整建议
}

Round 2 输出

{  
"reasoning": "布局思路说明,含尺寸验证",
"layoutRules": {
"symmetry": false,
"densitySpacing": 1.0,
"lDirection": "right"
},
"l2List": [
{
"role": "PRIMARY_SOFA",
"typeTag": "SOFA",
"zoneTag": "CORE",
"priority": "P0",
"boxSize": { "L": 2800, "D": 1000 }
},
{
"role": "COFFEE_TABLE",
"typeTag": "TABLE",
"zoneTag": "CORE",
"priority": "P0",
"boxSize": { "L": 1200, "D": 600 }
}
],
"relationships": [
{
"from": "COFFEE_TABLE",
"to": "PRIMARY_SOFA",
"type": "FRONT_OF",
"distance": 450
}
]
}

第二部分:三种模式分流

AI 对话完成后,同一份 LLM 返回结果按 3 种方式处理:

2.1 模式 1:用户 SolverType + 模板 Relationships

输入组装

{  
solverType: userSolverType, // 用户在 DebugPanel 选择的
l2List: decision.l2List, // LLM 返回的家具列表
relationships: generateRelationshipsFromTemplate(
userSolverType, // 用户选的类型
decision.l2List.map(i => i.role),
l1Input.boundingBox // 用于比例缩放
)
}

特点

  • SolverType 固定(用户选择)
  • Relationships 从 SOLVER_TEMPLATES 模板生成
  • 模板使用比例参数(如 distanceRatioD: 0.064 = 6.4% of L1.D),自动适配不同尺寸 L1

2.2 模式 2:LLM SolverType + 模板 Relationships

输入组装

{  
solverType: decision.solverType, // LLM 返回的
l2List: decision.l2List, // LLM 返回的
relationships: generateRelationshipsFromTemplate(
decision.solverType, // LLM 选的类型
decision.l2List.map(i => i.role),
l1Input.boundingBox
)
}

特点

  • SolverType 由 LLM 决定
  • Relationships 仍用模板(稳定性高)

2.3 模式 3:LLM SolverType + LLM Relationships

输入组装

{  
solverType: decision.solverType, // LLM 返回的
l2List: decision.l2List, // LLM 返回的
relationships: decision.relationships // LLM 返回的(完全自由)
}

特点

  • 完全由 LLM 决定
  • 灵活性最高,但稳定性取决于 LLM 输出质量

第三部分:Constraint Solver 求解流程

三种模式最终都调用同一个 solveByConstraints 函数。

3.1 Step 1:锚点定位

// 从 L1 类型配置获取锚点角色(通常是 PRIMARY_SOFA)  
const anchorRole = L1_TYPE_CONFIGS[l1.l1Type].anchorRole || 'PRIMARY_SOFA';

// 初始位置:x 居中, y 贴后墙(如果 wallAttach === 'back')
position = {
x: 0,
y: D / 2 - anchorBox.D / 2 // 贴后墙
}

3.2 Step 2:BFS 关系图扩散

1. 构建邻接表:from → [{to, relationship}]  
2. 多轮迭代(最多 20 轮):
- 遍历所有 relationships
- 如果 to 已解算且 from 未解算 → 解算 from
3. 根据关系类型计算 position 和 rotation

关系解算逻辑

typeposition 计算rotation
FRONT_OFy = to.y - toHalfD - distance - fromHalfD0
BESIDEx = to.x ± (toHalfL + distance + fromHalfL)0
PERPENDICULAR_ATTACH端部接合,考虑旋转后尺寸互换±90° (π/2)
UNDERx = to.x, y = to.y(层叠)0
FACING类似 FRONT_OF,更大 distance180° (π)
CORNER角落位置0
CENTER_OF与 to 中心对齐0

3.3 Step 3:边界校验(硬/软约束区分)

EDGE_TOLERANCE = 100mm(边缘容忍值)  

对每个家具:
├── FABRIC(地毯):
│ ├── 尺寸不超过 L1
│ └── 位置钳位确保完全在 L1 内(不允许骑线)

└── 其他家具:
├── 硬约束:中心点超出 L1 → 强制拉回
├── 软约束:边缘超出 >100mm → 缩回到容忍范围
└── 允许:边缘超出 ≤100mm → 允许骑线

3.4 Step 4:重叠检测与修复

过滤参与碰撞检测的容器(排除 FABRIC)  

迭代最多 10 轮:
├── 两两做 AABB 碰撞检测
├── 特殊跳过规则:
│ ├── 旋转的沙发类与茶几/边几(L型内角合理重叠)
│ └── 两个沙发类且有一个旋转了90°,<200mm 重叠视为接合容差
├── 检测到重叠:
│ └── 沿最小分离轴推开,MIN_GAP = 20mm
└── 推开后再做边界校验

3.5 Step 5:兜底缩放(shrinkToFit)

对溢出边界的家具(推开后仍溢出):  
├── 计算 X/Y 轴溢出量
├── 溢出 ≤ EDGE_TOLERANCE → 不处理
├── 溢出 > EDGE_TOLERANCE → 等比缩放
│ ├── 缩放下限:原尺寸的 60%
│ └── 缩放后重新校验 position
└── FABRIC 跳过缩放

3.6 Step 6:二次 overlap 检测

缩放后安全跑一轮 overlap 检测  
(防止缩放后产生新的重叠)

3.7 Step 7:输出

{  
templateId: string,
l1Type: string,
solverType: string,
solveMode: 'constraint',
totalBoundingBox: { L, D },
facingDir: number[],
layoutRules: {
symmetry: boolean,
densitySpacing: number,
lDirection: 'left' | 'right'
},
containers: Array<{
id: string,
role: string,
typeTag: string,
zoneTag: string,
priority: string,
box: { L: number, D: number },
position: { x: number, y: number },
rotation: number // 弧度
}>,
relationships: Array<ContainerRelationship>
}

第四部分:模板自适应机制(模式 1/2 使用)

4.1 SOLVER_TEMPLATES 设计

每个 SolverType 对应一套模板,包含:

  • 必须角色 requiredRoles
  • 可选角色 optionalRoles
  • 标准 relationships(使用比例参数
  • L1 尺寸范围 l1Range(用于兼容性检查)

关键:比例参数而非固定值

{  
from: 'COFFEE_TABLE',
to: 'PRIMARY_SOFA',
type: 'FRONT_OF',
params: { distanceRatioD: 0.064 } // 6.4% of L1.D
}

各 SolverType 的 FRONT_OF distance 比例(基于黄金样本统计)

SolverTypedistance / L1.D 中位数
Linear_I_Shape6.4%
Corner_L_Shape9.1%
U_Shape_Enclosed10.5%
Parallel_Facing19.9%

4.2 generateRelationshipsFromTemplate 缩放逻辑

// 根据 L1 实际尺寸计算 distance  
if (distanceRatioD !== undefined && l1Box) {
distance = l1Box.D * distanceRatioD;
// 限制范围:最小 150mm,最大 50% L1.D
distance = Math.max(150, Math.min(l1Box.D * 0.5, distance));
}

if (distanceRatioL !== undefined && l1Box) {
distance = l1Box.L * distanceRatioL;
// 限制范围:最小 0mm,最大 30% L1.L
distance = Math.max(0, Math.min(l1Box.L * 0.3, distance));
}

4.3 兼容性检查

checkL1Compatibility(solverType, l1Box)  
// 返回:
// - compatible: boolean
// - warnings: string[](如尺寸/比例不匹配)
// - suggestedTypes: SolverType[](推荐更合适的类型)

第五部分:三种模式对比总结

维度模式 1模式 2模式 3
SolverType 来源用户手动选择LLM 决定LLM 决定
Relationships 来源模板生成模板生成LLM 生成
稳定性最高取决于 LLM
灵活性最低中等最高
适用场景调试/对比基准平衡方案探索新布局

附录:完整数据流图

用户输入  


┌──────────────────────────────────────────────────────────┐
│ Round 1 Prompt │
│ L1尺寸 + 风格 + 关键词 → 选择 SolverType │
└──────────────────────────────────────────────────────────┘

▼ { solverType, reasoning }

┌──────────────────────────────────────────────────────────┐
│ Round 2 Prompt │
│ L1尺寸 + SolverType + 意图 + 家具目录 + Few-shot │
│ → 生成 l2List + relationships │
│ → 调用 check_space (可能多轮) │
└──────────────────────────────────────────────────────────┘

▼ { l2List, relationships, layoutRules }

├─────────────────┬─────────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 模式 1 │ │ 模式 2 │ │ 模式 3 │
│ User ST │ │ LLM ST │ │ LLM ST │
│ Tpl Rel │ │ Tpl Rel │ │ LLM Rel │
└─────────┘ └─────────┘ └─────────┘
│ │ │
└─────────────────┴─────────────────┘


┌──────────────────────────────────────────────────────────┐
│ Constraint Solver │
│ 1. 锚点定位 (PRIMARY_SOFA) │
│ 2. BFS 关系图扩散 (max 20 轮) │
│ 3. 边界校验 (硬: 中心, 软: 边缘 100mm) │
│ 4. Overlap 检测修复 (max 10 轮, AABB, 最小分离轴) │
│ 5. 兜底缩放 (min 60%, 仅溢出>100mm时) │
│ 6. 二次 Overlap 检测 │
└──────────────────────────────────────────────────────────┘


{ containers: [{position, rotation, size}] }


Canvas 渲染

相关文件索引

文件说明
AIChatPanel.tsxAI 对话面板,两轮对话逻辑
promptTemplate.tsRound 1/2 Prompt 构建
checkSpaceFit.tscheck_space Tool 实现
ComparisonView.tsx三模式对比视图
solverTemplates.ts6 种拓扑的 relationship 模板
solvers/constraintSolver.ts约束求解器核心逻辑
solvers/index.tsSolver 调度入口