【问题标题】:Find if a line intersects a sphere查找线是否与球体相交
【发布时间】:2010-09-19 20:55:23
【问题描述】:

尝试制作一个非常简单的布尔函数来判断一条线是否与球体相交。

这似乎不是我想要的,尽管问题很相似: Intersection of a line and a Sphere?

我也尝试过以下列出的算法:

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

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

没有真正的运气。

我最近的代码(在 Haskell 中)如下所示:

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)

如果 2 个点具有直接的站点线,则返回 true。 这适用于一些简单的情况,但不适用于其他应该有效的情况,例如:

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)

任何帮助将不胜感激。

【问题讨论】:

  • 你使用的算法应该是错误的。很容易看出,通过维度分析——topbot的维度是Area,result是无维度的; r 的维度是 Length,所以 result &lt; r 没有意义。
  • @KennyTM:很好的观察。默认情况下,可惜维度不是我们类型系统的一部分。它会捕获很多错误。

标签: algorithm haskell 3d geometry


【解决方案1】:

您使用了错误的公式。如果您的线表示为:

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)

【讨论】:

    【解决方案2】:

    我不知道这是否是最有效的做事方式,但要考虑的一件事是:

    如果直线到球心的垂直距离小于或等于球体的半径,则直线与球体相交。

    那么你的问题就变成了:如何计算点到线的距离?

    【讨论】:

      【解决方案3】:

      这是一个懒惰的答案,但是下面的页面应该有你想要的信息:http://www.devmaster.net/wiki/Ray-sphere_intersection

      更一般地说,在谷歌上搜索射线球交叉点而不是线球交叉点应该会产生大量直接的信息。

      另外,我认为这本质上是这个问题的重复:Testing whether a line segment intersects a sphere

      【讨论】:

        【解决方案4】:

        在我看来你想改用

        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)
        

        注意。我不知道 Haskell 的平方符号是什么,所以我在上面使用了^2

        e:工作 herehere

        【讨论】:

          猜你喜欢
          • 2011-01-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多