我在寻找一种算法来决定一个线段和一个轴对齐盒之间的远近相交点。
I'm looking for an algorithm that determines the near and far intersection points between a line segment and an axis-aligned box.
下面是我的方法的定义:
Here is my method definition:
public static Point3D[] IntersectionOfLineSegmentWithAxisAlignedBox(
Point3D rayBegin, Point3D rayEnd, Point3D boxCenter, Size3D boxSize)
如果线段不相交的盒子,该方法应该返回一个空三维点
阵列。
If the line segment doesn't intersect the box, the method should return an empty Point3D
array.
从我的研究,到目前为止,我已经遇到了一些研究论文和高度优化的算法,但他们似乎都用C ++编写,并需要多个长的类文件转换为C#。对于我而言,这东西是相当有效的,容易被人谁得到的点产品和跨产品,简单/短期将preferred理解。
From my research so far, I've come across some research papers with highly optimized algorithms, but they all seem to be written in C++ and would require multiple long class files to be converted to C#. For my purposes, something that is reasonably efficient, easy to understand by someone who gets dot products and cross products, and simple/short would be preferred.
推荐答案
下面是我最终使用:
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();
}
}
相关推荐
最新文章