笛卡儿坐标:在另一个点周围生成4个点的坐标

时间:2018-02-02 18:53:25

标签: python math

我想在球体上的一个点周围放置4个点(笛卡尔坐标:xyz),这4个点离中心点有多远(直线距离或球面距离)并不重要)但是我希望这4个点与中心点的距离D相同(理想情况下,5个点应该有+或x形状,所以一个北,一个南,一个东,一个南)。

我可以通过改变一个变量(x,y或z),然后保持另一个变量相同并根据公式x * x + y * y + z * z = radius * radius计算最后一个变量但是没有& #39; t给出好的结果。我也可以使用毕达哥拉斯定理来获得4个点和中心之间的距离,但我认为有一个更好的公式,我不知道(并且通过我的研究无法找到)

谢谢。

1 个答案:

答案 0 :(得分:1)

一些数学

AFAIU你的问题是你在球体上有一个球体和一个点,你想在同一个球体上再添加4个点,这些点会在目标点周围的球体表面上形成一种十字形。 / p>

我认为从矢量方面考虑这个问题会更容易。您有一个从球体中心到目标点的矢量 V ,大​​小为R。距目标点距离d的所有点都形成另一个球体。两个球体的交叉是一个圆圈。显然,这个圆圈位于与 V 正交的平面中。求解一个简单的方程组,您可以发现从目标点到该平面的距离为d^2/(2*R)。所以从原始球体中心到圆心的矢量:

Vc = V * (1 - d^2/(2*R^2))

,该圆的半径为

Rc = sqrt(d^2 - (d^2/(2*R))**2)

现在要选择4个点,您需要选择位于该平面中的两个正交单位向量 D1 {{ 1}} 即可。然后4分将是 D2 Vc + Rc*D1 Vc - Rc*D1 Vc + Rc*D2 。要执行此操作,您可以先选择 Vc - Rc*D2 修复D1并在 <中切换z =0x em> y

Vc

然后根据 D1 = (Vy/sqrt(Vx^2+Vy^2), -Vx/sqrt(Vx^2+Vy^2), 0) cross-product找到 D2 V 。这将有效,除非D1 = Vx = Vy(即 0 沿着{{1} } -axis)但在这种情况下你可以选择

V

部分代码

这是一些实现该数学的Python代码:

z

对于极端情况

D1 = (1,0,0)
D2 = (0,1,0)

即。对于中心位于def cross_product(v1, v2): return (v1[1] * v2[2] - v1[2] * v2[1], v1[2] * v2[0] - v1[0] * v2[2], v1[0] * v2[1] - v1[1] * v2[0]) def find_marks(sphereCenter, target, d): lsc = list(sphereCenter) lt0 = list(target) lt1 = map(lambda c1, c0: (c1 - c0), lt0, lsc) # shift everything as if sphereCenter is (0,0,0) rs2 = sum(map(lambda x: x ** 2, lt1)) # spehere radius**2 rs = rs2 ** 0.5 dv = d ** 2 / 2.0 / rs dvf = d ** 2 / 2.0 / rs2 lcc = map(lambda c: c * (1 - dvf), lt1) # center of the circle in the orthogonal plane rc = (d ** 2 - dv ** 2) ** 0.5 # orthogonal circle radius relEps = 0.0001 absEps = relEps * rs dir1 = (lt1[1], -lt1[0], 0) # select any direction orthogonal to the original vector dl1 = (lt1[0] ** 2 + lt1[1] ** 2) ** 0.5 # if original vector is (0,0, z) then we've got dir1 = (0,0,0) but we can use (1,0,0) as our vector if abs(dl1) < absEps: dir1 = (rc, 0, 0) dir2 = (0, rc, 0) else: dir1 = map(lambda c: rc * c / dl1, dir1) dir2 = cross_product(lt1, dir1) dl2 = sum(map(lambda c: c ** 2, dir2)) ** 0.5 dir2 = map(lambda c: rc * c / dl2, dir2) p1 = map(lambda c0, c1, c2: c0 + c1 + c2, lsc, lcc, dir1) p2 = map(lambda c0, c1, c2: c0 + c1 + c2, lsc, lcc, dir2) p3 = map(lambda c0, c1, c2: c0 + c1 - c2, lsc, lcc, dir1) p4 = map(lambda c0, c1, c2: c0 + c1 - c2, lsc, lcc, dir2) return [tuple(p1), tuple(p2), tuple(p3), tuple(p4)] 的半径为find_marks((0, 0, 0), (12, 5, 0), 13.0 * 2 ** 0.5) 的圆,目标点位于平行于13 - 平面的平面上的大圆上,(0,0,0),答案是

  

[(4.999999999999996,-12.000000000000004,0.0),   
(-5.329070518200751e-15,-2.220446049250313e-15,-13.0),   
(-5.000000000000006,12.0,0.0),   
(-5.329070518200751e-15,-2.220446049250313e-15,13.0)]

所以两点(第2和第4)只有两个xy - 极值,另外两个是d = sqrt(2)*R - 平面中目标点的90°旋转,看起来相当不错。

对于一个不那么极端的例子:

z

这是上一个示例,其中xy缩减为find_marks((1, 2, 3), (13, 7, 3), 1) 并且原始中心已移至d

  

[(13.34882784191617,6.06281317940119,3.0),   
(12.964497041420119,6.985207100591716,2.000739918710263),   
(12.580166240924067,7.907601021782242,3.0),   
(12.964497041420119,6.985207100591716,3.999260081289737)]

也看似合理

相关问题