【问题标题】:Cube sphere intersection test?立方体球相交测试?
【发布时间】:2011-01-02 15:12:55
【问题描述】:

最简单的方法是什么?我数学不及格,我在互联网上发现了相当复杂的公式……我希望是否有更简单的公式?

我只需要知道一个球体是否与一个立方体重叠,我不关心它在哪个点重叠等等。

我也希望它能够利用两个形状都是对称的这一事实。

编辑:立方体在 x、y、z 轴上直线对齐

【问题讨论】:

  • 复杂的不发,怎么知道有没有更简单的呢?
  • 好吧,我想你可以在头脑中编出一些简单的公式。但如果你不能,那么我认为它不可能比我发现的复杂的更简单......
  • 可能的复杂性主要是由于考虑了立方体的潜在方向。如果立方体的面平行于坐标平面,那么这些想法很容易解释。你的情况是立方体变量的方向?
  • 哦,我也忘了提这个事实,所以立方体确实根本没有旋转,边总是在 x、y、z 轴上笔直
  • @Newbie,你想知道立方体和球体是否相交,或者立方体是否完全在球体内?

标签: c++ intersection


【解决方案1】:

只看半个空格是不够的,你还必须考虑最接近的点:

借用亚当的符号:

假设一个轴对齐的立方体,让 C1 和 C2 为对角,S 为球心,R 为球体半径,并且两个物体都是实心的:

inline float squared(float v) { return v * v; }
bool doesCubeIntersectSphere(vec3 C1, vec3 C2, vec3 S, float R)
{
    float dist_squared = R * R;
    /* assume C1 and C2 are element-wise sorted, if not, do that now */
    if (S.X < C1.X) dist_squared -= squared(S.X - C1.X);
    else if (S.X > C2.X) dist_squared -= squared(S.X - C2.X);
    if (S.Y < C1.Y) dist_squared -= squared(S.Y - C1.Y);
    else if (S.Y > C2.Y) dist_squared -= squared(S.Y - C2.Y);
    if (S.Z < C1.Z) dist_squared -= squared(S.Z - C1.Z);
    else if (S.Z > C2.Z) dist_squared -= squared(S.Z - C2.Z);
    return dist_squared > 0;
}

【讨论】:

  • C1,C2,S 是什么意思?我假设 R = 球体的半径?
  • x = C1.X 是立方体最左边的面,C2.X 是最右边的面,​​C1.Y 是最底部的面,C2.Y​​ 是最上面的面, C1.Z 是最远的面,C2.Z 是最近的面。 S.{X, Y, Z} 是球心的坐标。
  • dist 的初始值是多少?它没有在那里声明
  • 我认为 OP 想知道立方体是否在球体内,而不是相反。
  • @mr_jigsaw:只需将squared 更改为abs。我想。
【解决方案2】:

Jim Arvo 在 Graphics Gems 2 中为此提供了一种算法,该算法适用于 N 维。我相信您想要在此页面底部的“案例 3”:http://www.ics.uci.edu/~arvo/code/BoxSphereIntersect.c 为您的情况清理的是:

bool BoxIntersectsSphere(Vec3 Bmin, Vec3 Bmax, Vec3 C, float r) {
  float r2 = r * r;
  dmin = 0;
  for( i = 0; i < 3; i++ ) {
    if( C[i] < Bmin[i] ) dmin += SQR( C[i] - Bmin[i] );
    else if( C[i] > Bmax[i] ) dmin += SQR( C[i] - Bmax[i] );     
  }
  return dmin <= r2;
}

【讨论】:

  • 这不是和 Ben Voigt 的回答完全一样吗? (只是想知道为什么这得到了赞成但他没有)。
  • @Newbie:我投了票,因为它有参考,但是代码是一样的
  • 我的没有提供参考,因为我没有使用过。我记住了欧几里得空间中的距离公式,剩下的就是简单的几何。
  • 能给个页码或章节名吗?
  • 我赞成这个,因为它比@BenVoigt 的回答更清楚
【解决方案3】:
// Assume clampTo is a new value. Obviously, don't move the sphere
closestPointBox = sphere.center.clampTo(box)

isIntersecting = sphere.center.distanceTo(closestPointBox) < sphere.radius

其他一切都只是优化。

哇,-2。艰难的人群。好的,这里的three.js 实现基本上是逐字逐句的。 https://github.com/mrdoob/three.js/blob/dev/src/math/Box3.js

intersectsSphere: ( function () {

    var closestPoint;

    return function intersectsSphere( sphere ) {

        if ( closestPoint === undefined ) closestPoint = new Vector3();

        // Find the point on the AABB closest to the sphere center.
        this.clampPoint( sphere.center, closestPoint );

        // If that point is inside the sphere, the AABB and sphere intersect.
        return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );

    };

} )(),

【讨论】:

  • 因为c++不是JS。
猜你喜欢
  • 2011-08-31
  • 2011-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多