我已經搜索範圍很廣,但尚未找到適合此問題的答案。給定球體上的兩條線,每條線都由它們的起點和終點確定,以確定它們是否相交以及它們在哪裏相交。我發現這個網站(http://mathforum.org/library/drmath/view/62205.html)通過一個很好的算法來處理兩個大圓的交點,儘管我堅持確定給定的點是否位於大圓的有限部分。球體表面上的測地線(最短距離路徑)之間的交點
我發現幾個網站聲稱他們已經實施了這個,包括一些問題在這裏和stackexchange,但他們似乎總是減少回到兩個大圓的交集。
蟒蛇類我寫如下,似乎差不多的工作:
class Geodesic(Boundary):
def _SecondaryInitialization(self):
self.theta_1 = self.point1.theta
self.theta_2 = self.point2.theta
self.phi_1 = self.point1.phi
self.phi_2 = self.point2.phi
sines = math.sin(self.phi_1) * math.sin(self.phi_2)
cosines = math.cos(self.phi_1) * math.cos(self.phi_2)
self.d = math.acos(sines - cosines * math.cos(self.theta_2 - self.theta_1))
self.x_1 = math.cos(self.theta_1) * math.cos(self.phi_1)
self.x_2 = math.cos(self.theta_2) * math.cos(self.phi_2)
self.y_1 = math.sin(self.theta_1) * math.cos(self.phi_1)
self.y_2 = math.sin(self.theta_2) * math.cos(self.phi_2)
self.z_1 = math.sin(self.phi_1)
self.z_2 = math.sin(self.phi_2)
self.theta_wraps = (self.theta_2 - self.theta_1 > PI)
self.phi_wraps = ((self.phi_1 < self.GetParametrizedCoords(0.01).phi and
self.phi_2 < self.GetParametrizedCoords(0.99).phi) or (
self.phi_1 > self.GetParametrizedCoords(0.01).phi) and
self.phi_2 > self.GetParametrizedCoords(0.99))
def Intersects(self, boundary):
A = self.y_1 * self.z_2 - self.z_1 * self.y_2
B = self.z_1 * self.x_2 - self.x_1 * self.z_2
C = self.x_1 * self.y_2 - self.y_1 * self.x_2
D = boundary.y_1 * boundary.z_2 - boundary.z_1 * boundary.y_2
E = boundary.z_1 * boundary.x_2 - boundary.x_1 * boundary.z_2
F = boundary.x_1 * boundary.y_2 - boundary.y_1 * boundary.x_2
try:
z = 1/math.sqrt(((B * F - C * E) ** 2/(A * E - B * D) ** 2)
+ ((A * F - C * D) ** 2/(B * D - A * E) ** 2) + 1)
except ZeroDivisionError:
return self._DealWithZeroZ(A, B, C, D, E, F, boundary)
x = ((B * F - C * E)/(A * E - B * D)) * z
y = ((A * F - C * D)/(B * D - A * E)) * z
theta = math.atan2(y, x)
phi = math.atan2(z, math.sqrt(x ** 2 + y ** 2))
if self._Contains(theta, phi):
return point.SPoint(theta, phi)
theta = (theta + 2* PI) % (2 * PI) - PI
phi = -phi
if self._Contains(theta, phi):
return spoint.SPoint(theta, phi)
return None
def _Contains(self, theta, phi):
contains_theta = False
contains_phi = False
if self.theta_wraps:
contains_theta = theta > self.theta_2 or theta < self.theta_1
else:
contains_theta = theta > self.theta_1 and theta < self.theta_2
phi_wrap_param = self._PhiWrapParam()
if phi_wrap_param <= 1.0 and phi_wrap_param >= 0.0:
extreme_phi = self.GetParametrizedCoords(phi_wrap_param).phi
if extreme_phi < self.phi_1:
contains_phi = (phi < max(self.phi_1, self.phi_2) and
phi > extreme_phi)
else:
contains_phi = (phi > min(self.phi_1, self.phi_2) and
phi < extreme_phi)
else:
contains_phi = (phi > min(self.phi_1, self.phi_2) and
phi < max(self.phi_1, self.phi_2))
return contains_phi and contains_theta
def _PhiWrapParam(self):
a = math.sin(self.d)
b = math.cos(self.d)
c = math.sin(self.phi_2)/math.sin(self.phi_1)
param = math.atan2(c - b, a)/self.d
return param
def _DealWithZeroZ(self, A, B, C, D, E, F, boundary):
if (A - D) is 0:
y = 0
x = 1
elif (E - B) is 0:
y = 1
x = 0
else:
y = 1/math.sqrt(((E - B)/(A - D)) ** 2 + 1)
x = ((E - B)/(A - D)) * y
theta = (math.atan2(y, x) + PI) % (2 * PI) - PI
return point.SPoint(theta, 0)
def GetParametrizedCoords(self, param_value):
A = math.sin((1 - param_value) * self.d)/math.sin(self.d)
B = math.sin(param_value * self.d)/math.sin(self.d)
x = A * math.cos(self.phi_1) * math.cos(self.theta_1) + (
B * math.cos(self.phi_2) * math.cos(self.theta_2))
y = A * math.cos(self.phi_1) * math.sin(self.theta_1) + (
B * math.cos(self.phi_2) * math.sin(self.theta_2))
z = A * math.sin(self.phi_1) + B * math.sin(self.phi_2)
new_phi = math.atan2(z, math.sqrt(x**2 + y**2))
new_theta = math.atan2(y, x)
return point.SPoint(new_theta, new_phi)
編輯:我忘了指定,如果兩條曲線決心相交,然後我需要有點路口。
這是一個奇妙和優雅的解決方案,是否兩條線相交。我忘了說明,在兩者相交的情況下,我也需要交點。例如,上面的Intersects方法可以工作,但是它具有多重性,因爲它可以計算以該段爲特徵的大圓的交點,這減少了我對檢測到的交點是否存在於段上的檢查不足。 – Jordan 2014-11-01 20:23:03
交叉點位於兩個平面上,所以它應該是矢量'm = cross(cross(a.v1,a.v2),cross(b.v1,b.v2))'的某個實數倍。唯一的問題是交點是否是'm'或'-m'的標準化。我認爲你可以通過計算任意三個點的行列式的符號來獲得,例如'det(a.v1,b.v1,b.v2)'。 – 2014-11-01 20:34:45
哇,那麼優雅! – ZpaceZombor 2017-04-28 12:42:28