Найти, если линия пересекает сферу - PullRequest
5 голосов
/ 20 сентября 2010

Попытка создать очень простую логическую функцию, которая будет определять, пересекает ли линия сферу.

Это не похоже на то, что я хочу, хотя вопрос был похож: Пересечениелиния и сфера?

Также я попробовал алгоритмы, перечисленные в:

http://www.docstoc.com/docs/7747820/Intersection-of-a-Line-and-a-Sphere

и

http://www.ccs.neu.edu/home/fell/CSU540/programs/RayTracingFormulas.htm

без особой удачи.

Мой последний код (на Хаскеле) выглядит следующим образом:

data Point = Point { x :: Float, y :: Float, z :: Float} deriving (Eq, Show, Read)
data Sphere = Sphere { center :: Point, radius :: Float } deriving (Eq, Show, Read)

inView :: Point -> Point -> Sphere -> Bool
inView (Point x1 y1 z1) (Point x2 y2 z2) (Sphere (Point x3 y3 z3) r)
  | result > 0 && result < r = False
  | otherwise                = True
  where result = top/bot
        top = (x3 - x1) * (x2 - x1) + (y3 - y1) * (y2 - y1) + (z3 - z1) * (z2 - z1)
        bot = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1)

Где он возвращает true, если 2 точки имеют прямую линию сайта,Это работает для некоторых простых случаев, но не работает для других, которые должны работать, например:

inView (Point {x = 43.64, y = -183.20, z = 187.37}) (Point {x = 42.04, y = -183.58, z = 187.37}) (Sphere (Point 0 0 0) 5)

Любая помощь будет принята.

Ответы [ 4 ]

2 голосов
/ 20 сентября 2010

Вы используете неправильное уравнение.Если ваша линия представлена ​​в виде:

p1 + u (p2 - p1)

(где u - скаляр), то top/bot находит u, который делает это выражение как можно ближе к центру сферы.

Поэтому я бы изменил ваш код:

where u = top/bot
      nearestPoint = {- p1 + u (p2 - p1) -}
      result = {- distance between nearestPoint and p3 -}

Заполните этот псевдокод, и вы должны быть золотыми.Вы просто неверно истолковали значение result.

Кстати, вы, вероятно, могли бы сильно очистить свой код, используя Data.VectorSpace.Я могу легко выписать свою поправку, используя ее:

import Data.VectorSpace

type Point = (Double, Double, Double)
inView :: Point -> Point -> Sphere -> Bool
inView p1 p2 (Sphere p3 r) = result < r
    where u = top/bot
          top = ...
          bot = ...
          nearestPoint = p1 ^+^ u *^ (p2 ^-^ p1)
          result = magnitude (p3 ^-^ nearestPoint)
1 голос
/ 21 сентября 2010

Я не знаю, является ли это наиболее эффективным способом сделать что-то, но нужно учитывать следующее:

Линия пересекает сферу, если расстояние от линии до центра сферы перпендикулярно.меньше или равен радиусу сферы.

Тогда возникает ваш вопрос: как рассчитать расстояние от точки до линии?

0 голосов
/ 20 сентября 2010

Мне кажется, что вместо этого вы хотите использовать

inView :: Point -> Point -> Sphere -> Bool
inView (Point x1 y1 z1) (Point x2 y2 z2) (Sphere (Point x3 y3 z3) r)
  | result > 0 && result < r^2 = False // is this correct? I know nothing about Haskell, but seems like this should be True
  | otherwise                  = True
  where result = -t1^2/t2 + t3
        t1 = (x3 - x1) * (x2 - x1) + (y3 - y1) * (y2 - y1) + (z3 - z1) * (z2 - z1)
        t2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1)
        t3 = (x3 - x1) * (x3 - x1) + (y3 - y1) * (y3 - y1) + (z3 - z1) * (z3 - z1)

NB. Я не знаю, что такое обозначение Хаскелла для квадрата, поэтому я использовал ^2 выше.

e: работает здесь и здесь

0 голосов
/ 20 сентября 2010

Это ленивый ответ, но на следующей странице должна быть информация, которую вы хотите: http://www.devmaster.net/wiki/Ray-sphere_intersection

В целом, поиск точки пересечения лучевой сферы, а не пересечения сферической линии, должен дать массу прямой информации.

Кроме того, я думаю, что это, по сути, дубликат этого вопроса: Проверка, пересекает ли отрезок прямой сферу

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...