如何从 5 个表面点中获得超球面中心点?

问题描述

我正在尝试在 4 维空间中实现一个 voronoi 采样器,这应该是一项非常简单的任务,但是选择了一个好的起点分布,由于缺乏均匀性,有时会生成一些非常倾斜的 voronoi 单元分布(我接受有关如何生成均匀随机点散射的建议)。

于是我开始研究生成质心voronoi细胞的案例,偶然发现了题目上的问题。我从假设可以从五个表面点定义一个 4D 超球面开始。

我什至得到了一些代码来从 3D 空间中的 三个 点中产生一个 3D 球体中心点(在这种情况下,这些点总是在球体的赤道中),我分享here。我还设法找到了从 四个 表面点中将球体的三维空间中心五分之一的代码,但是由于大量的矩阵行列式计算,它变得非常大,我承认它有点粉碎了我的希望自己将其扩展到 4D。

我在 https://math.stackexchange.com 中发现了很多演示,但这不是我可以轻松转换为代码的东西。

更新更新更新!!!

大家好,我终于在周末了,所以我可以给这些照片。

首先,我得到了以下 C# (Unity3D) 代码,我可以在视觉上确认它正在创造奇迹。当所有点都共面时,它显然会失败,但这在意料之中。

static public Vector3 TetrahedronCircumcenter3D(Vector3 a,Vector3 b,Vector3 c,Vector3 d)
{
    Vector3 ba = b - a; //all points from an 'a' point of view
    Vector3 ca = c - a;
    Vector3 da = d - a;
    Vector3 crosscd = Vector3.Cross(ca,da); //perpendicular vectors to those above
    Vector3 crossdb = Vector3.Cross(da,ba);
    Vector3 crossbc = Vector3.Cross(ba,ca);
    return a + (
        (
            ba.sqrMagnitude * crosscd +
            ca.sqrMagnitude * crossdb +
            da.sqrMagnitude * crossbc
        ) *
        (0.5f / (ba.x * crosscd.x + ba.y * crosscd.y + ba.z * crosscd.z)) // half point
    );
}

正如我所说,它在视觉上有效。

我从不幸丢失的链接中得到了这个,该链接解释了如何从垂直线的交叉点计算单纯形的外心。这两个词很重要,因为这就是我一直在寻找的:“单纯形外心”。单纯形是在 R^n 中可以得到的最简单的形状:R^2 中的三角形,R^3 中的四面体和 R^4 中的五边形等等。

然后我决定尝试将其扩展为简单地使用合理的方式将其扩展到 4D。我首先偶然发现了一个问题,除了 3-D 和(奇怪的)7-D 之外,不能指望两个向量之间有垂直叉积,我以为我已经完成了。但是一句话给出了下一个线索(这很明显,在有人说之后:你可以从 4-D 中的 3 个向量之间的叉积中得到一个垂直的 4-D 向量。搜索公式,我发现了一些甚至更好:code

扩展该代码以使用 Vector4 是微不足道的。

扩展代码如下所示:

static public Vector4 PentatopeCircumcenter4D(Vector4 a,Vector4 b,Vector4 c,Vector4 d,Vector4 e)
{
    Vector4 ba = b - a; //all points from an 'a' point of view
    Vector4 ca = c - a;
    Vector4 da = d - a;
    Vector4 ea = e - a;
    Vector4 crosscde = Crossproduct(ca,da,ea); //perpendicular vectors
    Vector4 crossdeb = Crossproduct(da,ea,ba);
    Vector4 crossebc = Crossproduct(ea,ba,ca);
    Vector4 crossbcd = Crossproduct(ba,ca,da);
    return a +
        (
            (
                crosscde * ba.sqrMagnitude +
                crossdeb * ca.sqrMagnitude +
                crossebc * da.sqrMagnitude +
                crossbcd * ea.sqrMagnitude
            ) *
            (0.5f / (ba.x * crosscde.x + ba.y * crosscde.y + ba.z * crosscde.z + ba.w * crosscde.w))
        );
}

这引出了下一个问题:如何确认这是有效的?

编辑:此处解释了基本原理:https://ctools.ece.utah.edu/Triangulation/TriangulationSphereCntr.pdf

编辑:它不适用于 4D。从点 a、b、c、d 和 e 到计算中心的距离不同。 a,b,d 是一致的。点 c 和 e 显示不同的距离。

编辑:在运行时手头没有线性代数求解器,并且无法减少其他来源中指定的系统,我不得不走矩阵的方式。代码有点广泛,但没什么可怕的。有一些 5x5 矩阵行列式,但我通过检查所有点和给定中心之间的距离来让它工作,现在看起来很完美。但是,上述尝试性解决方案不起作用。

解决方法

通过行列式(like (29) here 但有 4 个维度)的超球面方程对于 4D 来说是非常巨大的。

有一种方法需要计算逆矩阵(过程比较简单,矩阵代数中的标准问题)。

选择一个点作为基 X0 并制作 4 个向量 V1 = X1 - X0,V2 = X2 - X0 等等。 计算它们的半长

L1 = V1.norm / 2 ...

获取归一化(单位)向量:

U1 = V1 / (2*L1) ...

求解方程得到半径矢量R(从X0到超球面中心)

 | R.x |     |  U1.x  U1.y  U1.z  U1.w |               | L1 |
 | R.y |     |  U2.x  U2.y  U2.z  U2.w |.Inversed *    | L2 |
 | R.z |  =  |  U3.x  U3.y  U3.z  U3.w |               | L3 |
 | R.w |     |  U4.x  U4.y  U4.z  U4.w |               | L4 |

超球面中心是

 C = X0 + R

描述了这个方程的很好的基本原理here

它使用半径向量到 V 向量的投影,就像三角形外接圆的二维情况的中垂线方法一样

enter image description here enter image description here

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...