Algorithm 是否有一种优化的方法来查找三维立方体的最远角

Algorithm 是否有一种优化的方法来查找三维立方体的最远角,algorithm,geometry,Algorithm,Geometry,如果a有一个立方体C,有8个角(未对齐轴)和一个随机点p,我能做得比只检查所有角并选择距离p最大的角更好吗?或者考虑到立方体的对称性,是否有可能减少检查次数 将点p转换为立方体的原理基础,即它在其中轴向对齐(称为新点Q),原点是立方体在世界空间中的中心 要查找此帧中的最远点,F:以X轴为例,如果 Q.x>0然后F.x=-L,其中L是立方体的边长 Q.x0')。您还可以用一个加法来进行比较(X+bY+cZ+d>0->X+bY+cZ>d')。因此,总共有6次乘法、6次加法和3次比较 [对于数值稳定

如果a有一个立方体C,有8个角(未对齐轴)和一个随机点p,我能做得比只检查所有角并选择距离p最大的角更好吗?或者考虑到立方体的对称性,是否有可能减少检查次数

  • 将点
    p
    转换为立方体的原理基础,即它在其中轴向对齐(称为新点
    Q
    ),原点是立方体在世界空间中的中心

  • 要查找此帧中的最远点,
    F
    :以X轴为例,如果

    • Q.x>0
      然后
      F.x=-L
      ,其中
      L
      是立方体的边长
    • Q.x<0
      然后
      F.x=L
    • Q.x==0
      (严格地说
      abs(Q.x)
      ),然后
      F.x=0
  • 对其他两个轴也执行步骤2

  • 通过对步骤1中执行的点进行逆变换,将结果点
    F
    转换回世界空间。这将给出您想要的立方体上最远的点

  • 编辑:让我们看看为什么这可以更有效

    • 原始方法:8 X平方距离计算=8 X(3个浮点乘法+2个加法)

    • 新方法:2次矩阵乘法=2x(9次fp乘法+6次加法)

    如您所见,新方法使用更少的乘法和加法

  • 将点
    p
    转换为立方体的原理基础,即它在其中轴向对齐(称为新点
    Q
    ),原点是立方体在世界空间中的中心

  • 要查找此帧中的最远点,
    F
    :以X轴为例,如果

    • Q.x>0
      然后
      F.x=-L
      ,其中
      L
      是立方体的边长
    • Q.x<0
      然后
      F.x=L
    • Q.x==0
      (严格地说
      abs(Q.x)
      ),然后
      F.x=0
  • 对其他两个轴也执行步骤2

  • 通过对步骤1中执行的点进行逆变换,将结果点
    F
    转换回世界空间。这将给出您想要的立方体上最远的点

  • 编辑:让我们看看为什么这可以更有效

    • 原始方法:8 X平方距离计算=8 X(3个浮点乘法+2个加法)

    • 新方法:2次矩阵乘法=2x(9次fp乘法+6次加法)


    如您所见,新方法使用更少的乘法和加法。

    将随机点的坐标转换为与立方体对齐的局部坐标系。这需要9次乘法和9次加法

    如果本地系统以立方体为中心,三个符号测试将告诉您最远的角落


    轨迹法对问题有很好的理解

    如果你考虑随机点的所有位置,导致相同的答案(即相同的角索引;这是顶点的最远Voronoi图),则在立方体的三个等分平面定义的八个八角空间中划分空间。在八个区域中说出一个点需要三个二进制测试(

    Lg(8)
    )。有问题的测试会告诉点位于平面的哪一侧,这需要对仿射表达式进行求值
    aX+bY+cZ+d

    在“代数决策树”模型中,这可能是最优的


    更新

    因为只有符号才重要,所以可以对系数进行规格化,使其中一个为单位,并留出一个乘法(
    aX+bY+cZ+d>0->X+b'Y+c'Z+d>0'
    )。您还可以用一个加法来进行比较(
    X+bY+cZ+d>0->X+bY+cZ>d'
    )。因此,总共有6次乘法、6次加法和3次比较

    [对于数值稳定性,应除以最大系数。不幸的是,这会导致表达式依赖于它所在的系数。可以通过编写二十七个(!)索引计算函数(见下文)并通过指针调用右边的函数来避免这种情况。]


    假设系数已预先计算,以下表达式给出了角点索引,范围为
    [0,7]

    (X + b*Y + c*Z > d) + ((X + b'*Y + c'*Z > d') << 1) + ((X + b"*Y + c"*Z > d") << 2)
    

    (X+b*Y+c*Z>d)+((X+b'*Y+c'*Z>d')将随机点的坐标转换为与立方体对齐的局部坐标系。这需要9次乘法和9次加法

    如果本地系统以立方体为中心,三个符号测试将告诉您最远的角落


    轨迹法对问题有很好的理解

    如果你考虑随机点的所有位置,导致相同的答案(即相同的角索引;这是顶点的最远Voronoi图),则在立方体的三个等分平面定义的八个八角空间中划分空间。在八个区域中说出一个点需要三个二进制测试(<代码> LG(8)< /代码>).有问题的测试会告诉点位于平面的哪一侧,这需要计算仿射表达式

    aX+bY+cZ+d

    在“代数决策树”模型中,这可能是最优的


    更新

    因为只有符号是重要的,所以你可以规范化系数,使其中一个为单位,并留出一个乘法(
    aX+bY+cZ+d>0->X+b'Y+c'Z+d>0'
    )。你也可以用一个加法来交换一个比较(
    X+bY+cZ+d>0->X+bY+cZ>d'
    )。因此,总共有6个乘法、6个加法和3个比较

    [对于数值稳定性,应除以最大系数。不幸的是,这会导致表达式取决于它是什么。这可以通过写二十七(!)来避免
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public Vector3 FurthestPointFromFast(Vector3 q)
        {
            //BasisVectors( TransformMatrix, out var vx, out var vy, out var vz );
            var origin = BoxCorners.V000;
    
            // Get the pre-calculated principle
            // axes of the box with origin at V000
            Vector3 vx = BoxCorners.Px;
            Vector3 vy = BoxCorners.Py;
            Vector3 vz = BoxCorners.Pz;
    
            // Get the pre-calculated prinicple
            // axes lengths squared of the box at V000
            double lx = BoxCorners.Lx2;
            double ly = BoxCorners.Ly2;
            double lz = BoxCorners.Lz2;
    
            var d = q - origin;
            double tx = Vector3.Dot( d, vx );
            double ty = Vector3.Dot( d, vy );
            double tz = Vector3.Dot( d, vz );
    
            bool ix = tx < lx / 2;
            bool iy = ty < ly / 2;
            bool iz = tz < lz / 2;
    
            return ix
                ? (iy
                    ? (iz
                        ? BoxCorners.V111
                        : BoxCorners.V110)
                    : (iz
                        ? BoxCorners.V101
                        : BoxCorners.V100))
                : (iy
                    ? (iz
                        ? BoxCorners.V011
                        : BoxCorners.V010)
                    : (iz
                        ? BoxCorners.V001
                        : BoxCorners.V000));
        }
    
    public class BoxCorners
    {
        public Vector3 V111;
        public Vector3 V110;
        public Vector3 V101;
        public Vector3 V100;
        public Vector3 V011;
        public Vector3 V010;
        public Vector3 V001;
        public Vector3 V000;
    
        // These are the vectors starting at the box origin (V000)
        // They are precalculated and usefull in other algorithms
        #region Principle Axis
        public Vector3 Origin; 
        public Vector3 Px;
        public Vector3 Py;
        public Vector3 Pz;
        /// <summary>
        /// Px length squared
        /// </summary>
        public double Lx2;
        /// <summary>
        /// Py length squared
        /// </summary>
        public double Ly2;
        /// <summary>
        /// Pz length squared
        /// </summary>
        public double Lz2;
        #endregion
    
    
        public BoxCorners(Vector3 v000, Vector3 v001, Vector3 v010, Vector3 v011, Vector3 v100, Vector3 v101, Vector3 v110, Vector3 v111)
        {
            V000 = v000;
            V001 = v001;
            V010 = v010;
            V011 = v011;
            V100 = v100;
            V101 = v101;
            V110 = v110;
            V111 = v111;
    
            Origin = V000;
    
            Px = (V100 - Origin);
            Py = (V010 - Origin);
            Pz = (V001 - Origin);
    
            Lx2 = Px.LengthSquared();
            Ly2 = Py.LengthSquared();
            Lz2 = Py.LengthSquared();
        }
    
    }
    
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        void Acc(ref Vector3 v, ref Vector3 q, ref double max, ref Vector3 maxV)
        {
            var m = Vector3.DistanceSquared(v, q);
            if (!(m > max))
                return;
            max = m;
            maxV = v;
        }
    
        /// <summary>
        /// Return the furthest point on the box from the point
        /// </summary>
        /// <param name="q"></param>
        /// <returns></returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public Vector3 FurthestPointFrom(Vector3 q)
        {
    
            var max = 0.0;
            var bc = BoxCorners;
            var r = Vector3.Zero;
    
            Acc(ref bc.V111, ref q, ref max, ref r);
            Acc(ref bc.V110, ref q, ref max, ref r);
            Acc(ref bc.V101, ref q, ref max, ref r);
            Acc(ref bc.V100, ref q, ref max, ref r);
            Acc(ref bc.V011, ref q, ref max, ref r);
            Acc(ref bc.V010, ref q, ref max, ref r);
            Acc(ref bc.V001, ref q, ref max, ref r);
            Acc(ref bc.V000, ref q, ref max, ref r);
    
            return r;
        }