对象的准确边界框 [英] Accurate bounding box of an object

查看:25
本文介绍了对象的准确边界框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建对象的准确边界框,但似乎如果对象未与轴对齐(我认为),则框未与对象对齐.

I'm trying to create an accurate bounding box of an object, but it appears that if the object isn't aligned with the axis (I think) the box is not aligned with the object.

例如:

粉色和更接近橙色的顶点是这面墙的 Box3.min、Box3.max,但是你看到红色、绿色和蓝色不在这面墙上.您可以忽略 aqua 顶点.

The pink and closer orange vertices are the Box3.min, Box3.max of this wall, but you see the red and green and blue are not on that wall. You can ignore the aqua vertices.

这是创建边界框的代码(返回 Box3):

This is the code that creates the bounding box (returns Box3):

  static getWorldBoundingBox(model, dbId) {

    return new Promise(async(resolve, reject)=>{

      try{

        var fragIds = await ViewerToolkit.getFragIds(
          model, dbId);

        if(!fragIds.length){

          return reject('No geometry, invalid dbId?');
        }

        var fragList = model.getFragmentList();

        var fragbBox = new THREE.Box3();
        var nodebBox = new THREE.Box3();

        fragIds.forEach(function(fragId) {

          fragList.getWorldBounds(fragId, fragbBox);
          nodebBox.union(fragbBox);
        });

        return resolve(nodebBox);
      }
      catch(ex){

        return reject(ex);
      }
    });
  }

这就是我从最小、最大创建框的方式:

And that's how I create the box from the min, max:

    let ddd = new THREE.Vector3(min.x, min.y, min.z);
    let ddu = new THREE.Vector3(min.x, min.y, max.z);
    let dud = new THREE.Vector3(min.x, max.y, min.z);
    let udd = new THREE.Vector3(max.x, min.y, min.z);

    let duu = new THREE.Vector3(min.x, max.y, max.z);
    let uud = new THREE.Vector3(max.x, max.y, min.z);
    let udu = new THREE.Vector3(max.x, min.y, max.z);
    let uuu = new THREE.Vector3(max.x, max.y, max.z);

    this.drawVertices([ddd,ddu,dud,udd,duu,uud,udu,uuu]);

    let facesPoints = [
        {
            BL: ddd.clone(),
            UL: ddu.clone(),
            UR: udu.clone(),
            BR: udd.clone()
        },
        {
            BL: udd.clone(),
            UL: udu.clone(),
            UR: uuu.clone(),
            BR: uud.clone()
        },
        {
            BL: uud.clone(),
            UL: uuu.clone(),
            UR: duu.clone(),
            BR: dud.clone()
        },
        {
            BL: dud.clone(),
            UL: duu.clone(),
            UR: ddu.clone(),
            BR: ddd.clone()
        }
    ];

我想避免对所有顶点对的所有距离进行排序并取前两个的蛮力方法.

I want to avoid a brute force approach of sorting all distances of all pairs of vertices and taking the first two.

是否有另一种数据结构会暴露一个立方体的 8 个点,而不是只有 2 个点,我可以给它多边形来构建它,就像在上面的函数中一样?

Is there another data structure will expose 8 points of a cube instead of just 2 that I could give to it polygons to build it just like in the above function?

推荐答案

我找到了一种方法来做到这一点,首先我将所有顶点收集到一个 通用集 使用 Autodesk 的查看器扩展(网格数据)中的此功能:

I found a way to do this, first I collected all the vertices to a general set using this function from Autodesk's viewer extensions (Mesh data):

  static getMeshVertices(viewer, fragId) {

    var fragProxy = viewer.impl.getFragmentProxy(
      viewer.model,
      fragId);

    var renderProxy = viewer.impl.getRenderProxy(
      viewer.model,
      fragId);

    fragProxy.updateAnimTransform();

    var matrix = new THREE.Matrix4();
    fragProxy.getWorldMatrix(matrix);

    const verticesSet = new GeneralSet();
    const geometry = renderProxy.geometry;
    const attributes = geometry.attributes;

    if (attributes && attributes.index !== undefined) {

      const indices = attributes.index.array || geometry.ib;
      const positions = geometry.vb ? geometry.vb : attributes.position.array;
      const stride = geometry.vb ? geometry.vbstride : 3;
      let offsets = geometry.offsets;

      if (!offsets || offsets.length === 0) {

        offsets = [{ start: 0, count: indices.length, index: 0 }];
      }

      for (var oi = 0, ol = offsets.length; oi < ol; ++oi) {

        const start = offsets[oi].start;
        const count = offsets[oi].count;
        const index = offsets[oi].index;

        for (var i = start, il = start + count; i < il; i += 3) {

          const vA = new THREE.Vector3();
          const vB = new THREE.Vector3();
          const vC = new THREE.Vector3();
          const a = index + indices[i];
          const b = index + indices[i + 1];
          const c = index + indices[i + 2];

          vA.fromArray(positions, a * stride);
          vB.fromArray(positions, b * stride);
          vC.fromArray(positions, c * stride);

          vA.applyMatrix4(matrix);
          vB.applyMatrix4(matrix);
          vC.applyMatrix4(matrix);

          verticesSet.add(vA);
          verticesSet.add(vB);
          verticesSet.add(vC);
        }
      }

      return verticesSet;
    }
    else {

      var positions = geometry.vb ? geometry.vb : attributes.position.array;
      var stride = geometry.vb ? geometry.vbstride : 3;

      for (var i = 0, j = 0, il = positions.length; i < il; i += 3, j += 9) {
        let vA = new THREE.Vector3();
        let vB = new THREE.Vector3();
        let vC = new THREE.Vector3();
        var a = i;
        var b = i + 1;
        var c = i + 2;

        vA.fromArray(positions, a * stride);
        vB.fromArray(positions, b * stride);
        vC.fromArray(positions, c * stride);

        vA.applyMatrix4(matrix);
        vB.applyMatrix4(matrix);
        vC.applyMatrix4(matrix);

        verticesSet.add(vA);
        verticesSet.add(vB);
        verticesSet.add(vC);
      }

      return verticesSet;
    }
  }

然后我使用了这里的图直径算法:https://cs.stackexchange.com/a/213/43035 一次在顶点集上(好像该集代表一个完整的图)得到两个对角,我们称它们为 u, w.

Then I used a graph diameter algorithm from here: https://cs.stackexchange.com/a/213/43035 once on the set of vertices (as if the set represent a complete graph) to get two opposite corners, lets call them u, w.

然后我从顶点集中移除 u, w 并再次运行图直径,得到另外两个角.

Then I removed u, w from the set of vertices and ran the graph diameter again, getting the two other corners.

现在有了四个角,就可以生成所有其余的角,并对它们进行排序,有 3 个条件可以检查 4 个角中的每一个(这将显示其他 4 个角)、与相机的距离(更近或更远), 高度(上角或下角)和物体中间的左边或右边(使用十字和点,像这样 https://forum.unity3d.com/threads/left-right-test-function.31420/(他们有js代码).

Now with four corners it's possible to generate all the rest, and to sort them, there are 3 conditions to check for each of the 4 corners (which will reveal the 4 other corners), distance from camera (closer or further), height (upper or lower corner) and left or right from the middle of the object (using a cross and dot, like this https://forum.unity3d.com/threads/left-right-test-function.31420/ (they have js code)).

这将为您提供 8 个角,以便您知道哪个角在哪里,以及这些角在对象上,对象与轴对齐的方式无关紧要.

This will give you 8 corners such that you'll know which corner is where, and the corners are on the object, it doesn't matter how the object is aligned with the axes.

这篇关于对象的准确边界框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆