物体的精确边界框 [英] Accurate bounding box of an object

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

问题描述

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

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,但是您看到红色,绿色和蓝色不在该墙上。您可以忽略水顶点。

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;
    }
  }

然后我从这里使用图直径算法:<一次在一组顶点上进行一次href = https://cs.stackexchange.com/a/213/43035> 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天全站免登陆