从笛卡尔坐标到双球坐标的映射有奇怪的符号问题
Weird sign issue with mapping from cartesian to bispherical coordinates
我想将笛卡尔坐标 (x,y,z) 映射到双球坐标 (sigma,tau,phi) 并返回 wikipedia。
这是我的函数:
public static Vector3 ProjectBisphericalToCartesian(Vector3 bispherical, double a)
{
var sigma = (double)bispherical.X;
var tau = (double)bispherical.Y;
var phi = (double)bispherical.Z;
var d = Math.Cosh(tau) - Math.Cos(sigma);
var s = a / d;
var x = s * Math.Sin(sigma) * Math.Cos(phi);
var y = s * Math.Sin(sigma) * Math.Sin(phi);
var z = s * Math.Sinh(tau);
return new Vector3(
(float)x,
(float)y,
(float)z
);
}
public static Vector3 ProjectCartesianToBispherical(Vector3 cartesian, double a)
{
var x = (double)cartesian.X;
var y = (double)cartesian.Y;
var z = (double)cartesian.Z;
var R = Math.Sqrt(x * x + y * y + z * z);
var s = R * R + a * a;
var t = 2.0 * a * z;
var Q = Math.Sqrt(s * s - t * t);
var sigma = Math.Acos((R * R - a * a) / Q);
var tau = Asinh(t / Q);
var phi = Math.Atan(y / x);
return new Vector3(
(float)sigma,
(float)tau,
(float)phi
);
}
// sinh^-1 ("areasinus hyperbolicus")
private static double Asinh(double x)
{
return Math.Log(x + Math.Sqrt(x * x + 1.0));
}
我通过为 (x,y,z) 和 a 生成随机数来测试函数,将它们转换为双球坐标并返回笛卡尔坐标并检查它们是否等于原始笛卡尔坐标(最多一些小公差)。
事实证明,某些 笛卡尔坐标会翻转其 x 和 y 分量的符号(z 没问题),而其他坐标则不会。例如 {X:-5,3434 Y:2,569566 Z:-1,195607} 翻转 x 和 y 分量的符号,而 {X:7,586471 Y:-6,154929 Z:1 ,494778} 工作正常。
不幸的是,我在我的代码中找不到错误。
该问题似乎是由原始笛卡尔坐标中的负 x 值引起的,这将导致 x 和 y 的符号在转换和返回后翻转。我只是不明白为什么会这样。
有人知道这里发生了什么吗?
好吧,我实际上没有给你答案,但也许通过集思广益我们可以做到。
首先,在我看来,您确实正确地转录了维基百科公式。那么这是一个什么样的问题呢?要么 Math 函数与维基百科中引用的函数不完全相同,要么维基百科中存在错误。
我猜我不认为 Math 中的方法有不同的定义。这些功能已经存在了很长时间并且非常传统。也许维基百科是错误的。
您遇到的错误类型是符号错误。所以你应该看看当一个或两个输入的符号改变时会发生什么。例如,如果我们翻转 x 的符号,那么 phi 的符号在转换为双球面时会发生变化(它移动 180 度)。相应地,在转换为笛卡尔坐标时,如果我们翻转 phi 的符号,则 x 的符号会因 cos(phi) 而改变。
然而,如果我们翻转 x 和 y 的符号,那么 phi 的符号不会改变。其他双球计算也没有改变,因为它们只在平方中使用 x 和 y。另一方面,如果我们在转换为笛卡尔坐标时更改 phi 的符号,则 x 和 y 的符号会发生变化。所以笛卡尔系统中有两个点映射到相同的双球坐标,而对应的两个双球坐标确实映射回不同的笛卡尔坐标。看起来你需要在 x 和 y 到 phi 的转换中引入一个符号。 (或者,可以想象,其他双球坐标之一的符号可以弥补 phi 中符号的缺失。)
好的,我明白了。 Wolfram 提到了一些关于半平面的事情,所以我想到使用 Atan2(y, x) 而不是 Atan(y/x) 可以解决这个问题,它确实做到了。
我想将笛卡尔坐标 (x,y,z) 映射到双球坐标 (sigma,tau,phi) 并返回 wikipedia。
这是我的函数:
public static Vector3 ProjectBisphericalToCartesian(Vector3 bispherical, double a)
{
var sigma = (double)bispherical.X;
var tau = (double)bispherical.Y;
var phi = (double)bispherical.Z;
var d = Math.Cosh(tau) - Math.Cos(sigma);
var s = a / d;
var x = s * Math.Sin(sigma) * Math.Cos(phi);
var y = s * Math.Sin(sigma) * Math.Sin(phi);
var z = s * Math.Sinh(tau);
return new Vector3(
(float)x,
(float)y,
(float)z
);
}
public static Vector3 ProjectCartesianToBispherical(Vector3 cartesian, double a)
{
var x = (double)cartesian.X;
var y = (double)cartesian.Y;
var z = (double)cartesian.Z;
var R = Math.Sqrt(x * x + y * y + z * z);
var s = R * R + a * a;
var t = 2.0 * a * z;
var Q = Math.Sqrt(s * s - t * t);
var sigma = Math.Acos((R * R - a * a) / Q);
var tau = Asinh(t / Q);
var phi = Math.Atan(y / x);
return new Vector3(
(float)sigma,
(float)tau,
(float)phi
);
}
// sinh^-1 ("areasinus hyperbolicus")
private static double Asinh(double x)
{
return Math.Log(x + Math.Sqrt(x * x + 1.0));
}
我通过为 (x,y,z) 和 a 生成随机数来测试函数,将它们转换为双球坐标并返回笛卡尔坐标并检查它们是否等于原始笛卡尔坐标(最多一些小公差)。
事实证明,某些 笛卡尔坐标会翻转其 x 和 y 分量的符号(z 没问题),而其他坐标则不会。例如 {X:-5,3434 Y:2,569566 Z:-1,195607} 翻转 x 和 y 分量的符号,而 {X:7,586471 Y:-6,154929 Z:1 ,494778} 工作正常。
不幸的是,我在我的代码中找不到错误。 该问题似乎是由原始笛卡尔坐标中的负 x 值引起的,这将导致 x 和 y 的符号在转换和返回后翻转。我只是不明白为什么会这样。
有人知道这里发生了什么吗?
好吧,我实际上没有给你答案,但也许通过集思广益我们可以做到。
首先,在我看来,您确实正确地转录了维基百科公式。那么这是一个什么样的问题呢?要么 Math 函数与维基百科中引用的函数不完全相同,要么维基百科中存在错误。
我猜我不认为 Math 中的方法有不同的定义。这些功能已经存在了很长时间并且非常传统。也许维基百科是错误的。
您遇到的错误类型是符号错误。所以你应该看看当一个或两个输入的符号改变时会发生什么。例如,如果我们翻转 x 的符号,那么 phi 的符号在转换为双球面时会发生变化(它移动 180 度)。相应地,在转换为笛卡尔坐标时,如果我们翻转 phi 的符号,则 x 的符号会因 cos(phi) 而改变。
然而,如果我们翻转 x 和 y 的符号,那么 phi 的符号不会改变。其他双球计算也没有改变,因为它们只在平方中使用 x 和 y。另一方面,如果我们在转换为笛卡尔坐标时更改 phi 的符号,则 x 和 y 的符号会发生变化。所以笛卡尔系统中有两个点映射到相同的双球坐标,而对应的两个双球坐标确实映射回不同的笛卡尔坐标。看起来你需要在 x 和 y 到 phi 的转换中引入一个符号。 (或者,可以想象,其他双球坐标之一的符号可以弥补 phi 中符号的缺失。)
好的,我明白了。 Wolfram 提到了一些关于半平面的事情,所以我想到使用 Atan2(y, x) 而不是 Atan(y/x) 可以解决这个问题,它确实做到了。