2010-06-24 44 views
4

我正在尋找一種算法來確定線段和軸對齊框之間的近和遠交點。線段與C中軸對齊框的交點#

這裏是我的方法定義:

public static Point3D[] IntersectionOfLineSegmentWithAxisAlignedBox(
    Point3D rayBegin, Point3D rayEnd, Point3D boxCenter, Size3D boxSize) 

如果線段不相交中,該方法應該返回一個空Point3D陣列。

從我迄今爲止的研究中,我遇到了一些高度優化算法的研究論文,但它們似乎都是用C++編寫的,並且需要將多個長類文件轉換爲C#。就我的目的而言,合理高效的東西,獲得點積和交叉產品的人易於理解的東西,以及簡單/短的東西都是首選。

+0

我不知道算法,但我想返回'null'是有點不尋常。一個空數組更好,很明顯沒有相交的點(長度= 0),並且您不需要在使用代碼中執行空檢查。 – RichK 2010-06-24 12:27:45

+1

只是挑剔,但射線沒有終點 - 它在一個方向上是無限的。具有起點和終點的線是線段。 – 2010-06-25 00:19:31

+0

好點,@RichK ...我糾正了我的問題。 – devuxer 2010-06-25 03:04:42

回答

3

這裏是我最終使用:

public static List<Point3D> IntersectionOfLineSegmentWithAxisAlignedBox(
    Point3D segmentBegin, Point3D segmentEnd, Point3D boxCenter, Size3D boxSize) 
{ 
    var beginToEnd = segmentEnd - segmentBegin; 
    var minToMax = new Vector3D(boxSize.X, boxSize.Y, boxSize.Z); 
    var min = boxCenter - minToMax/2; 
    var max = boxCenter + minToMax/2; 
    var beginToMin = min - segmentBegin; 
    var beginToMax = max - segmentBegin; 
    var tNear = double.MinValue; 
    var tFar = double.MaxValue; 
    var intersections = new List<Point3D>(); 
    foreach (Axis axis in Enum.GetValues(typeof(Axis))) 
    { 
     if (beginToEnd.GetCoordinate(axis) == 0) // parallel 
     { 
      if (beginToMin.GetCoordinate(axis) > 0 || beginToMax.GetCoordinate(axis) < 0) 
       return intersections; // segment is not between planes 
     } 
     else 
     { 
      var t1 = beginToMin.GetCoordinate(axis)/beginToEnd.GetCoordinate(axis); 
      var t2 = beginToMax.GetCoordinate(axis)/beginToEnd.GetCoordinate(axis); 
      var tMin = Math.Min(t1, t2); 
      var tMax = Math.Max(t1, t2); 
      if (tMin > tNear) tNear = tMin; 
      if (tMax < tFar) tFar = tMax; 
      if (tNear > tFar || tFar < 0) return intersections; 

     } 
    } 
    if (tNear >= 0 && tNear <= 1) intersections.Add(segmentBegin + beginToEnd * tNear); 
    if (tFar >= 0 && tFar <= 1) intersections.Add(segmentBegin + beginToEnd * tFar); 
    return intersections; 
} 

public enum Axis 
{ 
    X, 
    Y, 
    Z 
} 

public static double GetCoordinate(this Point3D point, Axis axis) 
{ 
    switch (axis) 
    { 
     case Axis.X: 
      return point.X; 
     case Axis.Y: 
      return point.Y; 
     case Axis.Z: 
      return point.Z; 
     default: 
      throw new ArgumentException(); 
    } 
} 

public static double GetCoordinate(this Vector3D vector, Axis axis) 
{ 
    switch (axis) 
    { 
     case Axis.X: 
      return vector.X; 
     case Axis.Y: 
      return vector.Y; 
     case Axis.Z: 
      return vector.Z; 
     default: 
      throw new ArgumentException(); 
    } 
} 
+1

至少有一點解釋[這裏](http:// www。 garagegames.com/community/blogs/view/309)。 該算法計算從起點到交點必須走的線的比例。它通過將每個軸視爲一個一維問題來實現這一點,在這個問題中,它找到了需要添加到起始點以及到達交點的線的比例。 – mike 2015-05-10 15:26:01

+0

這可以通過先檢查邊界框來改進: 'if(begin> max || end mike 2015-05-10 15:32:27

2

好吧,對於一個軸對齊的盒子來說,它非常簡單:你必須找到你的光線與6個平面(由盒子面定義)的交點,然後檢查你發現的點與盒子頂點座標限制。