问题描述
我正在尝试在 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 向量的投影,就像三角形外接圆的二维情况的中垂线方法一样