# 放置区域 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 虽然迁移需要一些工作,但新系统的灵活性和可控性值得这个投入!