get3DBounds(获取包围盒)

2022-2-18

// 获取包围盒
async function get3DBounds({ dbid, viewer }) {
  const model = viewer.model;
  const it = model.getData().instanceTree;
  const tmpBox = new Float32Array(6);
  it.getNodeBox(dbid, tmpBox);
  return tmpBox;
}

async function getTmpBox(dbid, viewer) {
  const tmpBox = await get3DBounds({ dbid, viewer });
  return tmpBox;
}

async function resolveWorldCenter({ maxX, maxY, maxZ, minX, minY, minZ }) {
  const x = (maxX + minX) / 2;
  const y = (maxY + minY) / 2;
  const z = (maxZ + minZ) / 2;
  const pointcenter = new window.THREE.Vector3(x, y, z);
  return pointcenter;
}

/**
 * 获取单个或者多个构件的包围盒中心点
 * 多个构件中心点求解步骤:
 * 1.分别求出每个构件的tmpBox
 * 2.将每个tmpBox进行对比,分别找出X、Y、Z的最大值和最小值
 * 3.将最后得出的6个X、Y、Z的最大最小值进行计算,得到中心点worldPoint
 */
async function getPointCenter({ dbIdArray, viewer }) {
  if (dbIdArray.length > 1) {
    // 多个构件
    const xyz = await dbIdArray.reduce(
      async (prev, dbid) => {
        const prevObj = await prev;
        const [maxX, maxY, maxZ, minX, minY, minZ] = await getTmpBox(dbid, viewer);

        return {
          maxXArr: [...prevObj.maxXArr, maxX],
          maxYArr: [...prevObj.maxYArr, maxY],
          maxZArr: [...prevObj.maxZArr, maxZ],
          minXArr: [...prevObj.minXArr, minX],
          minYArr: [...prevObj.minYArr, minY],
          minZArr: [...prevObj.minZArr, minZ],
        };
      },
      {
        maxXArr: [],
        maxYArr: [],
        maxZArr: [],
        minXArr: [],
        minYArr: [],
        minZArr: [],
      }
    );

    const { maxXArr, maxYArr, maxZArr, minXArr, minYArr, minZArr } = xyz;

    const pointcenter = await resolveWorldCenter({
      maxX: Math.max(...maxXArr),
      maxY: Math.max(...maxYArr),
      maxZ: Math.max(...maxZArr),
      minX: Math.min(...minXArr),
      minY: Math.min(...minYArr),
      minZ: Math.min(...minZArr),
    });

    return pointcenter;
  } else if (dbIdArray.length === 1) {
    // 单个构件
    const [maxX, maxY, maxZ, minX, minY, minZ] = await getTmpBox(dbIdArray[0], viewer);
    const pointcenter = await resolveWorldCenter({ maxX, maxY, maxZ, minX, minY, minZ });

    return pointcenter;
  }
}

export { get3DBounds };
export default getPointCenter;