This commit is contained in:
2026-05-13 11:28:49 +08:00
parent 223fa5dd4e
commit 21255a701d
12 changed files with 1765 additions and 537 deletions

View File

@ -0,0 +1,407 @@
# 放置区域 API 迁移指南
## 概述
新的放置区域系统使用**参数化墙面定义**替代了旧的**包围盒自动生成**方案,提供更灵活、更精确的控制。
---
## 主要变化
### 旧方案的问题
- ❌ 依赖模型包围盒自动计算
- ❌ 只能生成固定的矩形四周
- ❌ 无法适应不规则形状
- ❌ 所有墙面必须使用相同的分割数
### 新方案的优势
- ✅ 直接定义每个墙面的起始和结束坐标
- ✅ 每个墙面可以有独立的分割数
- ✅ 支持任意数量的墙面1个、4个、N个
- ✅ 可以创建不规则形状L形、U形等
- ✅ 不依赖模型,坐标完全可控
---
## API 对比
### 旧 API已废弃
```typescript
import { AppDropZone } from './AppDropZone';
const appDropZone = new AppDropZone(scene);
// 旧的配置方式
const zones = appDropZone.generateDropZones({
modelName: 'myModel', // 依赖模型名称
divisions: 5, // 所有边使用相同分割数
color: '#21c7ff',
alpha: 0.3,
thickness: 2,
offset: 5, // 距离模型的偏移
scale: 1.0 // 缩放比例
});
// 返回 Mesh[]
```
### 新 API推荐
```typescript
import { AppDropZone } from './AppDropZone';
const appDropZone = new AppDropZone(scene);
// 新的配置方式
const zones = appDropZone.generateDropZones({
walls: [ // 墙面数组
{
name: 'front', // 墙面名称
startPoint: new Vector3(-50, 0, -50), // 起始点
endPoint: new Vector3(50, 0, -50), // 结束点
height: 30, // 高度
divisions: 5 // 这个墙面的分割数
},
{
name: 'back',
startPoint: new Vector3(50, 0, 50),
endPoint: new Vector3(-50, 0, 50),
height: 30,
divisions: 5
},
// ... 更多墙面
],
color: '#21c7ff',
alpha: 0.3,
thickness: 2,
showBorder: true, // 是否显示边框
borderColor: '#ffffff' // 边框颜色
});
// 返回 PlacementZoneInfo[]
```
---
## 迁移步骤
### 步骤 1确定墙面坐标
如果你之前使用模型包围盒,需要先获取模型的边界坐标:
```typescript
// 获取模型的包围盒坐标
function getModelBounds(scene: Scene, modelName: string) {
const mesh = scene.getMeshByName(modelName);
if (!mesh) return null;
mesh.computeWorldMatrix(true);
const boundingInfo = mesh.getBoundingInfo();
const min = boundingInfo.boundingBox.minimumWorld;
const max = boundingInfo.boundingBox.maximumWorld;
return {
minX: min.x,
maxX: max.x,
minY: min.y,
maxY: max.y,
minZ: min.z,
maxZ: max.z
};
}
```
### 步骤 2转换为墙面配置
```typescript
const bounds = getModelBounds(scene, 'myModel');
if (!bounds) return;
const { minX, maxX, minY, maxY, minZ, maxZ } = bounds;
const height = maxY - minY;
// 转换为新的墙面配置
const walls = [
{
name: 'front',
startPoint: new Vector3(minX, minY, minZ),
endPoint: new Vector3(maxX, minY, minZ),
height: height,
divisions: 5
},
{
name: 'back',
startPoint: new Vector3(maxX, minY, maxZ),
endPoint: new Vector3(minX, minY, maxZ),
height: height,
divisions: 5
},
{
name: 'left',
startPoint: new Vector3(minX, minY, maxZ),
endPoint: new Vector3(minX, minY, minZ),
height: height,
divisions: 5
},
{
name: 'right',
startPoint: new Vector3(maxX, minY, minZ),
endPoint: new Vector3(maxX, minY, maxZ),
height: height,
divisions: 5
}
];
```
### 步骤 3应用偏移如果需要
如果旧代码中使用了 `offset` 参数,需要手动调整坐标:
```typescript
const offset = 5;
// 前墙向外偏移
walls[0].startPoint.z -= offset;
walls[0].endPoint.z -= offset;
// 后墙向外偏移
walls[1].startPoint.z += offset;
walls[1].endPoint.z += offset;
// 左墙向外偏移
walls[2].startPoint.x -= offset;
walls[2].endPoint.x -= offset;
// 右墙向外偏移
walls[3].startPoint.x += offset;
walls[3].endPoint.x += offset;
```
### 步骤 4应用缩放如果需要
如果旧代码中使用了 `scale` 参数,需要调整坐标:
```typescript
const scale = 0.8; // 缩放到80%
const centerX = (minX + maxX) / 2;
const centerZ = (minZ + maxZ) / 2;
const scaledWidth = (maxX - minX) * scale;
const scaledDepth = (maxZ - minZ) * scale;
const scaledMinX = centerX - scaledWidth / 2;
const scaledMaxX = centerX + scaledWidth / 2;
const scaledMinZ = centerZ - scaledDepth / 2;
const scaledMaxZ = centerZ + scaledDepth / 2;
// 使用缩放后的坐标
walls[0].startPoint = new Vector3(scaledMinX, minY, scaledMinZ);
walls[0].endPoint = new Vector3(scaledMaxX, minY, scaledMinZ);
// ... 其他墙面类似
```
---
## 完整迁移示例
### 旧代码
```typescript
const appDropZone = new AppDropZone(scene);
const zones = appDropZone.generateDropZones({
modelName: 'warehouse',
divisions: 10,
color: '#21c7ff',
alpha: 0.3,
thickness: 2,
offset: 5,
scale: 0.9
});
```
### 新代码
```typescript
const appDropZone = new AppDropZone(scene);
// 1. 获取模型边界
const bounds = getModelBounds(scene, 'warehouse');
if (!bounds) return;
const { minX, maxX, minY, maxY, minZ, maxZ } = bounds;
// 2. 应用缩放
const scale = 0.9;
const centerX = (minX + maxX) / 2;
const centerZ = (minZ + maxZ) / 2;
const width = (maxX - minX) * scale;
const depth = (maxZ - minZ) * scale;
const height = maxY - minY;
const scaledMinX = centerX - width / 2;
const scaledMaxX = centerX + width / 2;
const scaledMinZ = centerZ - depth / 2;
const scaledMaxZ = centerZ + depth / 2;
// 3. 应用偏移
const offset = 5;
// 4. 生成放置区域
const zones = appDropZone.generateDropZones({
walls: [
{
name: 'front',
startPoint: new Vector3(scaledMinX, minY, scaledMinZ - offset),
endPoint: new Vector3(scaledMaxX, minY, scaledMinZ - offset),
height: height,
divisions: 10
},
{
name: 'back',
startPoint: new Vector3(scaledMaxX, minY, scaledMaxZ + offset),
endPoint: new Vector3(scaledMinX, minY, scaledMaxZ + offset),
height: height,
divisions: 10
},
{
name: 'left',
startPoint: new Vector3(scaledMinX - offset, minY, scaledMaxZ),
endPoint: new Vector3(scaledMinX - offset, minY, scaledMinZ),
height: height,
divisions: 10
},
{
name: 'right',
startPoint: new Vector3(scaledMaxX + offset, minY, scaledMinZ),
endPoint: new Vector3(scaledMaxX + offset, minY, scaledMaxZ),
height: height,
divisions: 10
}
],
color: '#21c7ff',
alpha: 0.3,
thickness: 2,
showBorder: true
});
```
---
## 新功能示例
### 1. 不同墙面使用不同分割数
```typescript
const zones = appDropZone.generateDropZones({
walls: [
{ name: 'front', ..., divisions: 10 }, // 前墙10块
{ name: 'back', ..., divisions: 10 }, // 后墙10块
{ name: 'left', ..., divisions: 5 }, // 左墙5块
{ name: 'right', ..., divisions: 5 } // 右墙5块
],
// ...
});
```
### 2. 创建L形区域
```typescript
const zones = appDropZone.generateDropZones({
walls: [
{
name: 'wall1',
startPoint: new Vector3(0, 0, 0),
endPoint: new Vector3(100, 0, 0),
height: 25,
divisions: 10
},
{
name: 'wall2',
startPoint: new Vector3(100, 0, 0),
endPoint: new Vector3(100, 0, 60),
height: 25,
divisions: 6
}
],
color: '#ff6b6b',
alpha: 0.4
});
```
### 3. 只创建单个墙面
```typescript
const zones = appDropZone.generateDropZones({
walls: [
{
name: 'display',
startPoint: new Vector3(-30, 0, 0),
endPoint: new Vector3(30, 0, 0),
height: 20,
divisions: 6
}
],
color: '#4ecdc4',
alpha: 0.35
});
```
---
## 获取放置区域信息
新API返回更详细的区域信息
```typescript
const zones = appDropZone.generateDropZones(config);
// 每个zone包含
zones.forEach(zone => {
console.log({
mesh: zone.mesh, // Babylon.js Mesh对象
wallName: zone.wallName, // 所属墙面名称
index: zone.index, // 在该墙面上的索引
center: zone.center, // 中心点坐标
width: zone.width, // 宽度
height: zone.height, // 高度
normal: zone.normal // 法线方向
});
});
// 获取特定墙面的所有区域
const frontZones = appDropZone.getZonesByWall('front');
// 获取特定的某一块
const zone = appDropZone.getZone('front', 2);
```
---
## 常见问题
### Q: 我必须迁移吗?
A: 旧的API已经被完全移除必须迁移到新API。
### Q: 如何快速迁移?
A: 使用上面的 `getModelBounds` 函数获取模型边界,然后转换为墙面配置。
### Q: 新API性能如何
A: 新API性能更好因为不需要计算包围盒直接使用预定义的坐标。
### Q: 可以动态调整墙面吗?
A: 可以,调用 `clearAll()` 清除旧的,然后用新坐标重新生成。
---
## 总结
新的放置区域系统提供了:
- ✅ 更精确的控制
- ✅ 更灵活的配置
- ✅ 更好的性能
- ✅ 更清晰的API
虽然迁移需要一些工作,但新系统的灵活性和可控性值得这个投入!