Есть ли способ получить линию, которая пересекает 3 сферы? - PullRequest
1 голос
/ 13 апреля 2020

Я пытаюсь найти способ получить линию (точку с моего текущего взгляда), которая пересекает 3 сферы. Они находятся близко друг к другу и не могут пересекаться каждый раз. Я также подумал, что можно представить его в виде кругов и перекрывающихся частей.

1 Ответ

0 голосов
/ 14 апреля 2020

Да, определенно есть способ. Вы можете сформулировать эту проблему как три квадратичных c неравенства. Я собираюсь предположить, что источником вашей системы координат является точка зрения. Если нет, вы должны выполнить изменение из любой системы координат, в которой представлена ​​конфигурация, в систему координат вашей точки зрения. У вас есть координаты центров P1, P2, P3 сфер и их соответствующие радиусы r1, r2, r3. Вы ищете вектор, выровненный по линии, проходящей через точку зрения (начало системы координат) и пересекающую все три сферы. Вы можете думать, что у вас есть экран на расстоянии h (h можно просто установить на 1), параллельном двум осям координат вашей системы координат точки обзора. Например, экран параллелен плоскости x, y, поэтому вы можете представить вектор как V = [V_x, V_y, h]. Затем линия, определяемая V, пересекает три сферы именно тогда, когда выполняются следующие квадратичные c неравенства для V:

(r1**2 - dot(P1,P1)) * dot(V,V) + (dot(P1,V))**2 > 0 
(r2**2 - dot(P2,P2)) * dot(V,V) + (dot(P2,V))**2 > 0 
(r3**2 - dot(P3,P3)) * dot(V,V) + (dot(P3,V))**2 > 0 

В дальнейшем я предлагаю геометрический подход c , что позволяет найти решение вышеупомянутых неравенств. Тем не менее, поскольку существуют различные особые (называемые ими вырожденные) случаи, нужно различать go для разных сценариев ios, что достаточно, чтобы не захотеть полностью записать это. Я просто напишу алгоритм для общего (невырожденного) случая. Я предполагаю, что ближайшая к источнику сфера полностью видима, в то время как две другие сферы имеют как видимую, так и невидимую части (и что с вашей точки зрения существует пересечение трех сфер, то есть существует решение неравенств ).

Идея состоит в том, что с учетом двух сфер и точки зрения, такой, что одна сфера, более удаленная, имеет как видимую, так и невидимую части, тогда существует ровно две линии через точку зрения, которые касаются в обе сферы. Итак, в вашем случае трех сфер S1, S2, S3 для любой пары сфер Si и Sj найдите единичный вектор Vk, который выровнен с касательной линией сфер Si и Sj, так что указанная касательная также пересекается третья сфера ск. Итак, если вы проецируете свои три сферы на экран, если смотреть с точки зрения, три единичных вектора V1, V2, V3 указывают на три вершины общего пересечения проекций сфер (которое является выпуклым множеством, потому что это пересечение выпуклых множеств, т. е. эллипсов). Следовательно, центроид трех векторов указывает на точку внутри общего пересечения проекций (поскольку последний является выпуклым). Таким образом, он определяет линию, которая пересекает все три сферы.

Заметьте, что есть много других, несколько более особых случаев, когда сферы могут находиться в разных положениях, поэтому вы должны их также охватить. Мне придется проверить грубый код ниже на наличие ошибок (в другой раз).

import numpy as np
import math

# I assume your point of view is the origin of the coordinate system, if not, 
# you have to perform a translation from whatever system your coordinates are 
# in to the point of view coordinate system
# 
# the 3 spheres defined by a center and a radius are
P1, r1
P2, r2
P3, r3

def area_Heron(a,b,c):
   p = (a + b + c)/2
   return math.sqrt(p*(p-a)*(p-b)*(p-c))

def line_through_sphere(V, P, r):
    return (r**2 - np.dot(P,P)) * np.dot(V,V) + (np.dot(P,V))**2 > 0 

def common_tangent(P1, r1, P2, r2, P3, r3):
   l1 = math.sqrt(np.dot(P1, P1))
   l2 = math.sqrt(np.dot(P2, P2))
   d1 = math.sqrt(l1**2 - r1**2)
   d2 = math.sqrt(l2**2 - r2**2)
   a1 = l1 / d1
   a2 = l2 / d2
   b1 = r1 / d1
   b2 = r2 / d2
   A1 = a1 * P1 / l1
   A2 = a2 * P2 / l2
   c = math.sqrt(np.dot(A2-A1, A2-A1))
   hc = 2 * area_Heron(a1, a2, c) / c
   c1 = math.sqrt(a1**2 - hc**2)
   c2 = math.sqrt(a2**2 - hc**2)   
   if c < c1:
       H = (- c2 * A1 + c1 * A2) / c
   elif c < c2:
       H = ( c2 * A1 - c1 * A2) / c
   else
       H = (c2 * A1 + c1 * A2) / c
   h = math.sqrt(hc**2 - 1) * hc
   B = cross(P1, P2)
   B = B / math.sqrt(np.dot(B, B))
   T1 = H + h * B
   T2 = H - h * B
   if line_through_sphere(T1, P3, r3):
      return T1 / math.sqrt(np.dot(T1,T1))
   if line_through_sphere(T2, P3, r3):
      return T2 / math.sqrt(np.dot(T2,T2))

Q1 = common_tangent(P2, r2, P3, r3, P1, r1)
Q2 = common_tangent(P3, r3, P1, r1, P2, r2)
Q3 = common_tangent(P1, r1, P2, r2, P3, r3)

Vector = (Q1 + Q2 + Q3) / 3

...