Using scipy.optimize.fsolve
如果初始猜测位于解的范围内,您可以找到给定函数的根。我用这种方法来解决你的问题,它似乎对我有用。唯一的缺点是它只为您提供一个交叉路口。要找到第二个,您必须修改初始条件,直到fsolve
找到第二个根。
首先,我们通过定义每个球体的(任意)半径和中心来定义球体:
a1 = np.array([0,0,0])
r1 = .4
a2 = np.array([.3,0,0])
r2 = .5
a3 = np.array([0,.3,0])
r3 = .5
然后我们定义如何在给定角度的情况下转换回笛卡尔坐标u,v
def position(a,r,u,v):
return a + r*np.array([np.cos(u)*np.sin(v),np.sin(u)*np.sin(v),np.cos(v)])
现在我们考虑一下我们需要求什么方程的根。对于任何交点,它都满足完美u1,v1,u2,v2,u3,v3
职位position(a1,r1,u1,v1) = position(a2,r2,u2,v2) = position(a3,r3,u3,v3)
是平等的。因此我们找到三个必须为零的方程,即两个位置向量的差。事实上,由于每个向量都有 3 个分量,因此我们有 9 个方程,足以确定 6 个变量。
我们找到最小化的函数为:
def f(args):
u1,v1,u2,v2,u3,v3,_,_,_ = args
pos1 = position(a1,r1,u1,v1)
pos2 = position(a2,r2,u2,v2)
pos3 = position(a3,r3,u3,v3)
return np.array([pos1 - pos2, pos1 - pos3, pos2 - pos3]).flatten()
fsolve
需要相同数量的输入和输出参数。由于我们有 9 个方程,但只有 6 个变量,我只使用了 3 个虚拟变量,以便尺寸匹配。需要展平最后一行的数组,因为fsolve
仅接受一维数组。
现在可以使用 fsolve 和(相当随机的)猜测找到交集:
guess = np.array([np.pi/4,np.pi/4,np.pi/4,np.pi/4,np.pi/4,np.pi/4,0,0,0])
x0 = fsolve(f,guess)
u1,v1,u2,v2,u3,v3,_,_,_ = x0
您可以通过将收到的角度插入到结果中来检查结果是否正确position
功能。