以下方法都是在Unity环境下基于C#语言测试通过的代码。
两条直线之间的距离代码参考如下:
// 计算两条直线之间的最短距离,这里借用了Ray射线类来替代表示直线
float LinesMinDist(Ray ray1, Ray ray2)
{
Vector3 p1 = ray1.origin;
Vector3 p2 = ray2.origin;
Vector3 d1 = ray1.direction;
Vector3 d2 = ray2.direction;
Vector3 n = Vector3.Cross(d1, d2);
// 方向向量叉乘为零,表示直线平行或重合
if (Mathf.Approximately(n.magnitude, 0))
{
// 平行或重合的情况
return Vector3.Distance(Vector3.Project(p2 - p1, d1) + p1, p2);
}
else
{
// 不平行的情况
return Vector3.Project(p1 - p2, n).magnitude;
}
}
两条线段之间的距离代码参考如下:
public class Segment
{
public Vector3 start;
public Vector3 end;
}
public float SegmentDistance(Segment seg1, Segment seg2)
{
Vector3 u = seg1.end - seg1.start;
Vector3 v = seg2.end - seg2.start;
Vector3 w = seg1.start - seg2.start;
float a = Vector3.Dot(u, u);
float b = Vector3.Dot(u, v);
float c = Vector3.Dot(v, v);
float d = Vector3.Dot(u, w);
float e = Vector3.Dot(v, w);
float D = a * c - b * b;
float sc, sN, sD = D;
float tc, tN, tD = D;
if (D < 0.01f)
{
sN = 0;
sD = 1;
tN = e;
tD = c;
}
else
{
sN = (b * e - c * d);
tN = (a * e - b * d);
if (sN < 0)
{
sN = 0;
tN = e;
tD = c;
}
else if (sN > sD)
{
sN = sD;
tN = e + b;
tD = c;
}
}
if (tN < 0)
{
tN = 0;
if (-d < 0)
{
sN = 0;
}
else if (-d > a)
{
sN = sD;
}
else
{
sN = -d;
sD = a;
}
}
else if (tN > tD)
{
tN = tD;
if ((-d + b) < 0)
{
sN = 0;
}
else if ((-d + b) > a)
{
sN = sD;
}
else
{
sN = (-d + b);
sD = a;
}
}
if (Mathf.Abs(sN) < 0.01f)
{
sc = 0;
}
else
{
sc = sN / sD;
}
if (Mathf.Abs(tN) < 0.01f)
{
tc = 0;
}
else
{
tc = tN / tD;
}
Vector3 dP = w + (sc * u) - (tc * v);
float distance1 = Mathf.Sqrt(Vector3.Dot(dP, dP));
return distance1;
}
点到线段距离2D版本代码如下:
public class Line2D
{
public Vector2 start;
public Vector2 end;
}
//计算点到线段的距离
public float DistPoint2DToLine2D(Vector2 point, Line2D line)
{
float distToStart = Vector2.Distance(point, line.start);
float distToEnd = Vector2.Distance(point, line.end);
float len = Vector2.Distance(line.start, line.end);
if (Mathf.Approximately(distToStart, 0) || Mathf.Approximately(distToEnd, 0)) return 0;
if (Mathf.Approximately(len, 0)) return distToStart;
//三角形一边长度平方与另外两边长度平方和的比较,大于是钝角三角形,小于是锐角三角形, 等于是直角三角形)
if (distToStart * distToStart >= len * len + distToEnd * distToEnd) return distToEnd;
if (len * len + distToStart * distToStart <= distToEnd * distToEnd) return distToStart;
//利用三角形的面积求高(点到垂足的距离)
float p = (len + distToStart + distToEnd) * 0.5f;
float area = Mathf.Sqrt(p * (p - distToEnd) * (p - distToStart) * (p - len));
return 2 * area / len;
}
点到线段距离3D版本代码如下:
public class Line
{
public Vector3 start;
public Vector3 end;
}
public float DistPointToLine(Vector3 point, Line line)
{
float distToStart = Vector3.Distance(point, line.start);
float distToEnd = Vector3.Distance(point, line.end);
float len = Vector3.Distance(line.start, line.end);
if (Mathf.Approximately(distToStart, 0) || Mathf.Approximately(distToEnd, 0)) return 0;
if (Mathf.Approximately(len, 0)) return distToStart;
//三角形一边长度平方与另外两边长度平方和的比较,大于是钝角三角形,小于是锐角三角形, 等于是直角三角形)
if (distToStart * distToStart >= len * len + distToEnd * distToEnd) return distToEnd;
if (len * len + distToStart * distToStart <= distToEnd * distToEnd) return distToStart;
//利用三角形的面积求高(点到垂足的距离)
float p = (len + distToStart + distToEnd) * 0.5f;
float area = Mathf.Sqrt(p * (p - distToEnd) * (p - distToStart) * (p - len));
return 2 * area / len;
}
点到直线距离3D版本如下:
float DistPointToLine(Vector3 point, Vector3 pSegA, Vector3 pSegB)
{
Vector3 vecAB = pSegA - pSegB;
Vector3 vecAP = pSegA - point;
float magOfCross = Vector3.Cross(vecAP, vecAB).magnitude;
return magOfCross / vecAB.magnitude;
}
该文提供了一组在Unity3D环境中使用C#语言计算两条直线之间、两条线段之间以及点到线段距离的代码示例。这些方法涉及到了Ray类、向量运算以及三角形几何知识,对于游戏开发中的碰撞检测和几何计算具有实用价值。

1027

被折叠的 条评论
为什么被折叠?



